aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_utilities/blocksdat_file.h1
-rw-r--r--src/blockchain_utilities/bootstrap_file.h1
-rw-r--r--src/blocks/checkpoints.datbin244676 -> 261572 bytes
-rw-r--r--src/checkpoints/checkpoints.cpp11
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/utf8.h114
-rw-r--r--src/crypto/crypto.cpp6
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp2
-rw-r--r--src/cryptonote_core/blockchain.cpp97
-rw-r--r--src/cryptonote_core/blockchain.h1
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp37
-rw-r--r--src/cryptonote_core/cryptonote_core.h14
-rw-r--r--src/cryptonote_core/tx_pool.cpp16
-rw-r--r--src/cryptonote_core/tx_pool.h4
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h3
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl31
-rw-r--r--src/daemon/rpc_command_executor.cpp3
-rw-r--r--src/device/device_ledger.cpp4
-rw-r--r--src/device_trezor/device_trezor.cpp4
-rw-r--r--src/device_trezor/trezor/transport.cpp3
-rw-r--r--src/mnemonics/language_base.h74
-rw-r--r--src/multisig/multisig.cpp7
-rw-r--r--src/p2p/net_node.inl5
-rw-r--r--src/ringct/bulletproofs.cc20
-rw-r--r--src/ringct/rctOps.cpp12
-rw-r--r--src/ringct/rctOps.h1
-rw-r--r--src/ringct/rctSigs.cpp5
-rw-r--r--src/ringct/rctTypes.h3
-rw-r--r--src/rpc/core_rpc_server.cpp64
-rw-r--r--src/rpc/core_rpc_server_error_codes.h2
-rw-r--r--src/rpc/daemon_handler.cpp3
-rw-r--r--src/rpc/daemon_messages.cpp106
-rw-r--r--src/rpc/daemon_messages.h6
-rw-r--r--src/rpc/message.cpp14
-rw-r--r--src/rpc/message.h6
-rw-r--r--src/rpc/rpc_args.cpp4
-rw-r--r--src/rpc/rpc_payment.cpp14
-rw-r--r--src/rpc/rpc_payment.h2
-rw-r--r--src/rpc/zmq_server.cpp1
-rw-r--r--src/serialization/json_object.cpp88
-rw-r--r--src/serialization/json_object.h104
-rw-r--r--src/simplewallet/simplewallet.cpp69
-rw-r--r--src/simplewallet/simplewallet.h6
-rw-r--r--src/version.cpp.in2
-rw-r--r--src/wallet/api/wallet.cpp2
-rw-r--r--src/wallet/message_store.cpp103
-rw-r--r--src/wallet/message_store.h3
-rw-r--r--src/wallet/wallet2.cpp106
-rw-r--r--src/wallet/wallet2.h11
-rw-r--r--src/wallet/wallet_rpc_server.cpp9
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h6
51 files changed, 792 insertions, 421 deletions
diff --git a/src/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h
index 72b7afc17..1accfbba2 100644
--- a/src/blockchain_utilities/blocksdat_file.h
+++ b/src/blockchain_utilities/blocksdat_file.h
@@ -43,7 +43,6 @@
#include <algorithm>
#include <cstdio>
#include <fstream>
-#include <boost/iostreams/copy.hpp>
#include <atomic>
#include "common/command_line.h"
diff --git a/src/blockchain_utilities/bootstrap_file.h b/src/blockchain_utilities/bootstrap_file.h
index 1e6ef5d81..db0556175 100644
--- a/src/blockchain_utilities/bootstrap_file.h
+++ b/src/blockchain_utilities/bootstrap_file.h
@@ -41,7 +41,6 @@
#include <algorithm>
#include <cstdio>
#include <fstream>
-#include <boost/iostreams/copy.hpp>
#include <atomic>
#include "common/command_line.h"
diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat
index b14f9e8d2..fa58387ab 100644
--- a/src/blocks/checkpoints.dat
+++ b/src/blocks/checkpoints.dat
Binary files differ
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index 4a4b3c5c2..620bc5ce7 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -34,6 +34,7 @@
#include "string_tools.h"
#include "storages/portable_storage_template_helper.h" // epee json include
#include "serialization/keyvalue_serialization.h"
+#include <functional>
#include <vector>
using namespace epee;
@@ -133,11 +134,9 @@ namespace cryptonote
//---------------------------------------------------------------------------
uint64_t checkpoints::get_max_height() const
{
- std::map< uint64_t, crypto::hash >::const_iterator highest =
- std::max_element( m_points.begin(), m_points.end(),
- ( boost::bind(&std::map< uint64_t, crypto::hash >::value_type::first, _1) <
- boost::bind(&std::map< uint64_t, crypto::hash >::value_type::first, _2 ) ) );
- return highest->first;
+ if (m_points.empty())
+ return 0;
+ return m_points.rbegin()->first;
}
//---------------------------------------------------------------------------
const std::map<uint64_t, crypto::hash>& checkpoints::get_points() const
@@ -211,6 +210,8 @@ namespace cryptonote
ADD_CHECKPOINT(1775600, "1c6e01c661dc22cab939e79ec6a5272190624ce8356d2f7b958e4f9a57fdb05e");
ADD_CHECKPOINT(1856000, "9b57f17f29c71a3acd8a7904b93c41fa6eb8d2b7c73936ce4f1702d14880ba29");
ADD_CHECKPOINT(1958000, "98a5d6e51afdf3146e0eefb10a66e8648d8d4d5c2742be8835e976ba217c9bb2");
+ ADD_CHECKPOINT(2046000, "5e867f0b8baefed9244a681df97fc885d8ab36c3dfcd24c7a3abf3b8ac8b8314");
+ ADD_CHECKPOINT(2092500, "c4e00820c9c7989b49153d5e90ae095a18a11d990e82fcc3be54e6ed785472b5");
return true;
}
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index f06737b31..35b3555a2 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -86,7 +86,8 @@ set(common_private_headers
updates.h
aligned.h
timings.h
- combinator.h)
+ combinator.h
+ utf8.h)
monero_private_headers(common
${common_private_headers})
diff --git a/src/common/utf8.h b/src/common/utf8.h
new file mode 100644
index 000000000..60247f1b2
--- /dev/null
+++ b/src/common/utf8.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2019, 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.
+
+#pragma once
+
+#include <cctype>
+#include <cwchar>
+#include <stdexcept>
+
+namespace tools
+{
+ template<typename T, typename Transform>
+ inline T utf8canonical(const T &s, Transform t = [](wint_t c)->wint_t { return c; })
+ {
+ T sc = "";
+ size_t avail = s.size();
+ const char *ptr = s.data();
+ wint_t cp = 0;
+ int bytes = 1;
+ char wbuf[8], *wptr;
+ while (avail--)
+ {
+ if ((*ptr & 0x80) == 0)
+ {
+ cp = *ptr++;
+ bytes = 1;
+ }
+ else if ((*ptr & 0xe0) == 0xc0)
+ {
+ if (avail < 1)
+ throw std::runtime_error("Invalid UTF-8");
+ cp = (*ptr++ & 0x1f) << 6;
+ cp |= *ptr++ & 0x3f;
+ --avail;
+ bytes = 2;
+ }
+ else if ((*ptr & 0xf0) == 0xe0)
+ {
+ if (avail < 2)
+ throw std::runtime_error("Invalid UTF-8");
+ cp = (*ptr++ & 0xf) << 12;
+ cp |= (*ptr++ & 0x3f) << 6;
+ cp |= *ptr++ & 0x3f;
+ avail -= 2;
+ bytes = 3;
+ }
+ else if ((*ptr & 0xf8) == 0xf0)
+ {
+ if (avail < 3)
+ throw std::runtime_error("Invalid UTF-8");
+ cp = (*ptr++ & 0x7) << 18;
+ cp |= (*ptr++ & 0x3f) << 12;
+ cp |= (*ptr++ & 0x3f) << 6;
+ cp |= *ptr++ & 0x3f;
+ avail -= 3;
+ bytes = 4;
+ }
+ else
+ throw std::runtime_error("Invalid UTF-8");
+
+ cp = t(cp);
+ if (cp <= 0x7f)
+ bytes = 1;
+ else if (cp <= 0x7ff)
+ bytes = 2;
+ else if (cp <= 0xffff)
+ bytes = 3;
+ else if (cp <= 0x10ffff)
+ bytes = 4;
+ else
+ throw std::runtime_error("Invalid code point UTF-8 transformation");
+
+ wptr = wbuf;
+ switch (bytes)
+ {
+ case 1: *wptr++ = cp; break;
+ case 2: *wptr++ = 0xc0 | (cp >> 6); *wptr++ = 0x80 | (cp & 0x3f); break;
+ case 3: *wptr++ = 0xe0 | (cp >> 12); *wptr++ = 0x80 | ((cp >> 6) & 0x3f); *wptr++ = 0x80 | (cp & 0x3f); break;
+ case 4: *wptr++ = 0xf0 | (cp >> 18); *wptr++ = 0x80 | ((cp >> 12) & 0x3f); *wptr++ = 0x80 | ((cp >> 6) & 0x3f); *wptr++ = 0x80 | (cp & 0x3f); break;
+ default: throw std::runtime_error("Invalid UTF-8");
+ }
+ *wptr = 0;
+ sc.append(wbuf, bytes);
+ cp = 0;
+ bytes = 1;
+ }
+ return sc;
+ }
+}
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
index 0ec992de9..8a03f28bb 100644
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -294,6 +294,7 @@ namespace crypto {
sc_mulsub(&sig.r, &sig.c, &unwrap(sec), &k);
if (!sc_isnonzero((const unsigned char*)sig.r.data))
goto try_again;
+ memwipe(&k, sizeof(k));
}
bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
@@ -390,6 +391,8 @@ namespace crypto {
// sig.r = k - sig.c*r
sc_mulsub(&sig.r, &sig.c, &unwrap(r), &k);
+
+ memwipe(&k, sizeof(k));
}
bool crypto_ops::check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig) {
@@ -560,6 +563,7 @@ POP_WARNINGS
random_scalar(sig[i].c);
random_scalar(sig[i].r);
if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
+ memwipe(&k, sizeof(k));
local_abort("invalid pubkey");
}
ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
@@ -573,6 +577,8 @@ POP_WARNINGS
hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h);
sc_sub(&sig[sec_index].c, &h, &sum);
sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &unwrap(sec), &k);
+
+ memwipe(&k, sizeof(k));
}
bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image,
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index b3400abc7..cb6d1ec91 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -160,6 +160,8 @@ namespace cryptonote
if (tx.version >= 2 && !is_coinbase(tx))
{
rct::rctSig &rv = tx.rct_signatures;
+ if (rv.type == rct::RCTTypeNull)
+ return true;
if (rv.outPk.size() != tx.vout.size())
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad outPk size in tx " << get_transaction_hash(tx));
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 2571e4203..4a3e2f08f 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -86,7 +86,7 @@ DISABLE_VS_WARNINGS(4267)
//------------------------------------------------------------------
Blockchain::Blockchain(tx_memory_pool& tx_pool) :
- m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
+ m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_reset_timestamps_and_difficulties_height(true), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(true), m_db_sync_threshold(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(false),
m_long_term_block_weights_window(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
m_long_term_effective_median_block_weight(0),
@@ -427,6 +427,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
if (num_popped_blocks > 0)
{
m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = true;
m_hardfork->reorganize_from_chain_height(get_current_blockchain_height());
uint64_t top_block_height;
crypto::hash top_block_hash = get_tail_id(top_block_height);
@@ -567,6 +568,7 @@ block Blockchain::pop_block_from_blockchain()
CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = true;
block popped_block;
std::vector<transaction> popped_txs;
@@ -644,6 +646,7 @@ bool Blockchain::reset_and_set_genesis_block(const block& b)
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = true;
invalidate_block_template_cache();
m_db->reset();
m_db->drop_alt_blocks();
@@ -812,12 +815,20 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph
// less blocks than desired if there aren't enough.
difficulty_type Blockchain::get_difficulty_for_next_block()
{
+ LOG_PRINT_L3("Blockchain::" << __func__);
+
+ std::stringstream ss;
+ bool print = false;
+
+ int done = 0;
+ ss << "get_difficulty_for_next_block: height " << m_db->height() << std::endl;
if (m_fixed_difficulty)
{
return m_db->height() ? m_fixed_difficulty : 1;
}
- LOG_PRINT_L3("Blockchain::" << __func__);
+start:
+ difficulty_type D = 0;
crypto::hash top_hash = get_tail_id();
{
@@ -826,21 +837,32 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
// something a bit out of date, but that's fine since anything which
// requires the blockchain lock will have acquired it in the first place,
// and it will be unlocked only when called from the getinfo RPC
+ ss << "Locked, tail id " << top_hash << ", cached is " << m_difficulty_for_next_block_top_hash << std::endl;
if (top_hash == m_difficulty_for_next_block_top_hash)
- return m_difficulty_for_next_block;
+ {
+ ss << "Same, using cached diff " << m_difficulty_for_next_block << std::endl;
+ D = m_difficulty_for_next_block;
+ }
}
CRITICAL_REGION_LOCAL(m_blockchain_lock);
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties;
uint64_t height;
- top_hash = get_tail_id(height); // get it again now that we have the lock
- ++height; // top block height to blockchain height
+ auto new_top_hash = get_tail_id(height); // get it again now that we have the lock
+ ++height;
+ if (!(new_top_hash == top_hash)) D=0;
+ ss << "Re-locked, height " << height << ", tail id " << new_top_hash << (new_top_hash == top_hash ? "" : " (different)") << std::endl;
+ top_hash = new_top_hash;
+
// ND: Speedup
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
// then when the next block difficulty is queried, push the latest height data and
// pop the oldest one from the list. This only requires 1x read per height instead
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
+ bool check = false;
+ if (m_reset_timestamps_and_difficulties_height)
+ m_timestamps_and_difficulties_height = 0;
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= DIFFICULTY_BLOCKS_COUNT)
{
uint64_t index = height - 1;
@@ -855,8 +877,12 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
m_timestamps_and_difficulties_height = height;
timestamps = m_timestamps;
difficulties = m_difficulties;
+ check = true;
}
- else
+ //else
+ std::vector<uint64_t> timestamps_from_cache = timestamps;
+ std::vector<difficulty_type> difficulties_from_cache = difficulties;
+
{
uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(DIFFICULTY_BLOCKS_COUNT));
if (offset == 0)
@@ -869,22 +895,68 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
timestamps.reserve(height - offset);
difficulties.reserve(height - offset);
}
+ ss << "Looking up " << (height - offset) << " from " << offset << std::endl;
for (; offset < height; offset++)
{
timestamps.push_back(m_db->get_block_timestamp(offset));
difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
}
+ if (check) if (timestamps != timestamps_from_cache || difficulties !=difficulties_from_cache)
+ {
+ ss << "Inconsistency XXX:" << std::endl;
+ ss << "top hash: "<<top_hash << std::endl;
+ ss << "timestamps: " << timestamps_from_cache.size() << " from cache, but " << timestamps.size() << " without" << std::endl;
+ ss << "difficulties: " << difficulties_from_cache.size() << " from cache, but " << difficulties.size() << " without" << std::endl;
+ ss << "timestamps_from_cache:" << std::endl; for (const auto &v :timestamps_from_cache) ss << " " << v << std::endl;
+ ss << "timestamps:" << std::endl; for (const auto &v :timestamps) ss << " " << v << std::endl;
+ ss << "difficulties_from_cache:" << std::endl; for (const auto &v :difficulties_from_cache) ss << " " << v << std::endl;
+ ss << "difficulties:" << std::endl; for (const auto &v :difficulties) ss << " " << v << std::endl;
+
+ uint64_t dbh = m_db->height();
+ uint64_t sh = dbh < 10000 ? 0 : dbh - 10000;
+ ss << "History from -10k at :" << dbh << ", from " << sh << std::endl;
+ for (uint64_t h = sh; h < dbh; ++h)
+ {
+ uint64_t ts = m_db->get_block_timestamp(h);
+ difficulty_type d = m_db->get_block_cumulative_difficulty(h);
+ ss << " " << h << " " << ts << " " << d << std::endl;
+ }
+ print = true;
+ }
m_timestamps_and_difficulties_height = height;
m_timestamps = timestamps;
m_difficulties = difficulties;
}
+
size_t target = get_difficulty_target();
difficulty_type diff = next_difficulty(timestamps, difficulties, target);
CRITICAL_REGION_LOCAL1(m_difficulty_lock);
m_difficulty_for_next_block_top_hash = top_hash;
m_difficulty_for_next_block = diff;
+ if (D && D != diff)
+ {
+ ss << "XXX Mismatch at " << height << "/" << top_hash << "/" << get_tail_id() << ": cached " << D << ", real " << diff << std::endl;
+ print = true;
+ }
+
+ ++done;
+ if (done == 1 && D && D != diff)
+ {
+ print = true;
+ ss << "Might be a race. Let's see what happens if we try again..." << std::endl;
+ epee::misc_utils::sleep_no_w(100);
+ goto start;
+ }
+ ss << "Diff for " << top_hash << ": " << diff << std::endl;
+ if (print)
+ {
+ MGINFO("START DUMP");
+ MGINFO(ss.str());
+ MGINFO("END DUMP");
+ MGINFO("Please send moneromooo on Freenode the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
+ }
return diff;
}
//------------------------------------------------------------------
@@ -914,6 +986,7 @@ bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
}
m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = true;
// remove blocks from blockchain until we get back to where we should be.
while (m_db->height() != rollback_height)
@@ -950,6 +1023,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = true;
// if empty alt chain passed (not sure how that could happen), return false
CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
@@ -1639,6 +1713,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = true;
uint64_t block_height = get_block_height(b);
if(0 == block_height)
{
@@ -2493,6 +2568,7 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
}
db_rtxn_guard rtxn_guard(m_db);
+ total_height = get_current_blockchain_height();
blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
CHECK_AND_ASSERT_MES(m_db->get_blocks_from(start_height, 3, max_count, FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE, blocks, pruned, true, get_miner_tx_hash),
false, "Error getting blocks");
@@ -4317,7 +4393,14 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync)
try
{
if (m_batch_success)
+ {
m_db->batch_stop();
+ if (m_reset_timestamps_and_difficulties_height)
+ {
+ m_timestamps_and_difficulties_height = 0;
+ m_reset_timestamps_and_difficulties_height = false;
+ }
+ }
else
m_db->batch_abort();
success = true;
@@ -5028,7 +5111,7 @@ void Blockchain::cancel()
}
#if defined(PER_BLOCK_CHECKPOINT)
-static const char expected_block_hashes_hash[] = "fce1dc7c17f7679f5f447df206b8f5fe2ef6b1a2845e59f650850a0ef00d265f";
+static const char expected_block_hashes_hash[] = "8b48d259d4b1126801b1f329683a26e1d16237420197cd3ccc76af2c55a36e83";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{
if (get_checkpoints == nullptr || !m_fast_sync)
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 3a89cc5df..82051ecd4 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -1067,6 +1067,7 @@ namespace cryptonote
std::vector<uint64_t> m_timestamps;
std::vector<difficulty_type> m_difficulties;
uint64_t m_timestamps_and_difficulties_height;
+ bool m_reset_timestamps_and_difficulties_height;
uint64_t m_long_term_block_weights_window;
uint64_t m_long_term_effective_median_block_weight;
mutable crypto::hash m_long_term_block_weights_cache_tip_hash;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 3ff3c77e2..619c5be3e 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -263,14 +263,14 @@ namespace cryptonote
m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns);
}
//-----------------------------------------------------------------------------------------------
- bool core::update_checkpoints()
+ bool core::update_checkpoints(const bool skip_dns /* = false */)
{
if (m_nettype != MAINNET || m_disable_dns_checkpoints) return true;
if (m_checkpoints_updating.test_and_set()) return true;
bool res = true;
- if (time(NULL) - m_last_dns_checkpoints_update >= 3600)
+ if (!skip_dns && time(NULL) - m_last_dns_checkpoints_update >= 3600)
{
res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, true);
m_last_dns_checkpoints_update = time(NULL);
@@ -650,7 +650,7 @@ namespace cryptonote
r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty, get_checkpoints);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
- r = m_mempool.init(max_txpool_weight);
+ r = m_mempool.init(max_txpool_weight, m_nettype == FAKECHAIN);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
// now that we have a valid m_blockchain_storage, we can clean out any
@@ -669,7 +669,8 @@ namespace cryptonote
// load json & DNS checkpoints, and verify them
// with respect to what blocks we already have
- CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
+ const bool skip_dns_checkpoints = !command_line::get_arg(vm, arg_dns_checkpoints);
+ CHECK_AND_ASSERT_MES(update_checkpoints(skip_dns_checkpoints), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
// DNS versions checking
if (check_updates_string == "disabled")
@@ -1308,9 +1309,9 @@ namespace cryptonote
std::vector<crypto::hash> tx_hashes{};
tx_hashes.resize(tx_blobs.size());
- cryptonote::transaction tx{};
for (std::size_t i = 0; i < tx_blobs.size(); ++i)
{
+ cryptonote::transaction tx{};
if (!parse_and_validate_tx_from_blob(tx_blobs[i], tx, tx_hashes[i]))
{
LOG_ERROR("Failed to parse relayed transaction");
@@ -1655,7 +1656,6 @@ namespace cryptonote
m_starter_message_showed = true;
}
- 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));
@@ -1666,31 +1666,6 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
- bool core::check_fork_time()
- {
- if (m_nettype == FAKECHAIN)
- return true;
-
- HardFork::State state = m_blockchain_storage.get_hard_fork_state();
- el::Level level;
- switch (state) {
- case HardFork::LikelyForked:
- level = el::Level::Warning;
- MCLOG_RED(level, "global", "**********************************************************************");
- MCLOG_RED(level, "global", "Last scheduled hard fork is too far in the past.");
- MCLOG_RED(level, "global", "We are most likely forked from the network. Daemon update needed now.");
- MCLOG_RED(level, "global", "**********************************************************************");
- break;
- case HardFork::UpdateNeeded:
- level = el::Level::Info;
- MCLOG(level, "global", el::Color::Default, "Last scheduled hard fork time suggests a daemon update will be released within the next couple months.");
- break;
- default:
- break;
- }
- return true;
- }
- //-----------------------------------------------------------------------------------------------
uint8_t core::get_ideal_hard_fork_version() const
{
return get_blockchain_storage().get_ideal_hard_fork_version();
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 255645efc..68c5651f1 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -699,7 +699,7 @@ namespace cryptonote
*
* @note see Blockchain::update_checkpoints()
*/
- bool update_checkpoints();
+ bool update_checkpoints(const bool skip_dns = false);
/**
* @brief tells the daemon to wind down operations and stop running
@@ -1001,18 +1001,6 @@ namespace cryptonote
bool check_tx_inputs_keyimages_domain(const transaction& tx) const;
/**
- * @brief checks HardFork status and prints messages about it
- *
- * Checks the status of HardFork and logs/prints if an update to
- * the daemon is necessary.
- *
- * @note see Blockchain::get_hard_fork_state and HardFork::State
- *
- * @return true
- */
- bool check_fork_time();
-
- /**
* @brief attempts to relay any transactions in the mempool which need it
*
* @return true
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 469319824..696bc88d4 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -116,7 +116,7 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
- tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_cookie(0)
+ tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_cookie(0), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_mine_stem_txes(false)
{
}
@@ -1121,7 +1121,7 @@ namespace cryptonote
// See `insert_key_images`.
if (1 < found->second.size() || *(found->second.cbegin()) != txid)
return true;
- return m_blockchain.txpool_tx_matches_category(txid, relay_category::broadcasted);
+ return m_blockchain.txpool_tx_matches_category(txid, relay_category::legacy);
}
return false;
}
@@ -1351,13 +1351,18 @@ namespace cryptonote
for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
{
txpool_tx_meta_t meta;
- if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta) && !meta.matches(relay_category::legacy))
+ if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
{
MERROR(" failed to find tx meta");
continue;
}
- LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase));
+ LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method());
+ if (!meta.matches(relay_category::legacy) && !(m_mine_stem_txes && meta.get_relay_method() == relay_method::stem))
+ {
+ LOG_PRINT_L2(" tx relay method is " << (unsigned)meta.get_relay_method());
+ continue;
+ }
if (meta.pruned)
{
LOG_PRINT_L2(" tx is pruned");
@@ -1522,7 +1527,7 @@ namespace cryptonote
return n_removed;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::init(size_t max_txpool_weight)
+ bool tx_memory_pool::init(size_t max_txpool_weight, bool mine_stem_txes)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -1578,6 +1583,7 @@ namespace cryptonote
lock.commit();
}
+ m_mine_stem_txes = mine_stem_txes;
m_cookie = 0;
// Ignore deserialization error
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 292d427e2..18ef0340b 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -205,10 +205,11 @@ namespace cryptonote
* @brief loads pool state (if any) from disk, and initializes pool
*
* @param max_txpool_weight the max weight in bytes
+ * @param mine_stem_txes whether to mine txes in stem relay mode
*
* @return true
*/
- bool init(size_t max_txpool_weight = 0);
+ bool init(size_t max_txpool_weight = 0, bool mine_stem_txes = false);
/**
* @brief attempts to save the transaction pool state to disk
@@ -603,6 +604,7 @@ private:
size_t m_txpool_max_weight;
size_t m_txpool_weight;
+ bool m_mine_stem_txes;
mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache;
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index e2ad3727f..3055474ef 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -51,7 +51,8 @@ PUSH_WARNINGS
DISABLE_VS_WARNINGS(4355)
#define LOCALHOST_INT 2130706433
-#define CURRENCY_PROTOCOL_MAX_OBJECT_REQUEST_COUNT 500
+#define CURRENCY_PROTOCOL_MAX_OBJECT_REQUEST_COUNT 100
+static_assert(CURRENCY_PROTOCOL_MAX_OBJECT_REQUEST_COUNT >= BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4, "Invalid CURRENCY_PROTOCOL_MAX_OBJECT_REQUEST_COUNT");
namespace cryptonote
{
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index f8e032fde..cd0b059fe 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -308,9 +308,9 @@ namespace cryptonote
if (version >= 6 && version != hshd.top_version)
{
if (version < hshd.top_version && version == m_core.get_ideal_hard_fork_version())
- MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version than we think (" <<
+ MDEBUG(context << " peer claims higher version than we think (" <<
(unsigned)hshd.top_version << " for " << (hshd.current_height - 1) << " instead of " << (unsigned)version <<
- ") - we may be forked from the network and a software upgrade may be needed");
+ ") - we may be forked from the network and a software upgrade may be needed, or that peer is broken or malicious");
return false;
}
}
@@ -793,6 +793,12 @@ namespace cryptonote
int t_cryptonote_protocol_handler<t_core>::handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context)
{
MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_FLUFFY_MISSING_TX (" << arg.missing_tx_indices.size() << " txes), block hash " << arg.block_hash);
+ if (context.m_state == cryptonote_connection_context::state_before_handshake)
+ {
+ LOG_ERROR_CCONTEXT("Requested fluffy tx before handshake, dropping connection");
+ drop_connection(context, false, false);
+ return 1;
+ }
std::vector<std::pair<cryptonote::blobdata, block>> local_blocks;
std::vector<cryptonote::blobdata> local_txs;
@@ -884,6 +890,8 @@ namespace cryptonote
int t_cryptonote_protocol_handler<t_core>::handle_notify_get_txpool_complement(int command, NOTIFY_GET_TXPOOL_COMPLEMENT::request& arg, cryptonote_connection_context& context)
{
MLOG_P2P_MESSAGE("Received NOTIFY_GET_TXPOOL_COMPLEMENT (" << arg.hashes.size() << " txes)");
+ if(context.m_state != cryptonote_connection_context::state_normal)
+ return 1;
std::vector<std::pair<cryptonote::blobdata, block>> local_blocks;
std::vector<cryptonote::blobdata> local_txs;
@@ -987,6 +995,12 @@ namespace cryptonote
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)
{
+ if (context.m_state == cryptonote_connection_context::state_before_handshake)
+ {
+ LOG_ERROR_CCONTEXT("Requested objects before handshake, dropping connection");
+ drop_connection(context, false, false);
+ return 1;
+ }
MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_GET_OBJECTS (" << arg.blocks.size() << " blocks)");
if (arg.blocks.size() > CURRENCY_PROTOCOL_MAX_OBJECT_REQUEST_COUNT)
{
@@ -1717,6 +1731,12 @@ skip:
int t_cryptonote_protocol_handler<t_core>::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, cryptonote_connection_context& context)
{
MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_CHAIN (" << arg.block_ids.size() << " blocks");
+ if (context.m_state == cryptonote_connection_context::state_before_handshake)
+ {
+ LOG_ERROR_CCONTEXT("Requested chain before handshake, dropping connection");
+ drop_connection(context, false, false);
+ return 1;
+ }
NOTIFY_RESPONSE_CHAIN_ENTRY::request r;
if(!m_core.find_blockchain_supplement(arg.block_ids, !arg.prune, r))
{
@@ -1907,6 +1927,10 @@ skip:
const uint32_t local_stripe = tools::get_pruning_stripe(m_core.get_blockchain_pruning_seed());
if (local_stripe == 0)
return false;
+ // don't request pre-bulletprooof pruned blocks, we can't reconstruct their weight (yet)
+ static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
+ if (first_block_height + nblocks - 1 < bp_fork_height)
+ return false;
// assumes the span size is less or equal to the stripe size
bool full_data_needed = tools::get_pruning_stripe(first_block_height, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES) == local_stripe
|| tools::get_pruning_stripe(first_block_height + nblocks - 1, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES) == local_stripe;
@@ -2083,7 +2107,8 @@ skip:
skip_unneeded_hashes(context, false);
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
- bool sync_pruned_blocks = m_sync_pruned_blocks && m_core.get_blockchain_pruning_seed();
+ static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
+ bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
if (span.second > 0)
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 034d49918..859cfc92a 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -511,7 +511,7 @@ bool t_rpc_command_executor::show_status() {
}
std::stringstream str;
- str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections")
+ str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %u(out)+%u(in) connections")
% (unsigned long long)ires.height
% (unsigned long long)net_height
% get_sync_percentage(ires)
@@ -521,7 +521,6 @@ bool t_rpc_command_executor::show_status() {
% get_mining_speed(cryptonote::difficulty_type(ires.wide_difficulty) / ires.target)
% (unsigned)hfres.version
% get_fork_extra_info(hfres.earliest_height, net_height, ires.target)
- % (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked")
% (unsigned)ires.outgoing_connections_count
% (unsigned)ires.incoming_connections_count
;
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 222a84d3f..0783b00b0 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -1468,8 +1468,8 @@ namespace hw {
offset = set_command_header(INS_PREFIX_HASH,2,cnt);
len = pref_length - pref_offset;
//options
- if (len > (BUFFER_SEND_SIZE-7)) {
- len = BUFFER_SEND_SIZE-7;
+ if (len > (BUFFER_SEND_SIZE-offset-3)) {
+ len = BUFFER_SEND_SIZE-offset-3;
this->buffer_send[offset] = 0x80;
} else {
this->buffer_send[offset] = 0x00;
diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp
index 8bde1cb75..367327c70 100644
--- a/src/device_trezor/device_trezor.cpp
+++ b/src/device_trezor/device_trezor.cpp
@@ -678,8 +678,10 @@ namespace trezor {
throw exc::TrezorException("Trezor firmware 2.0.10 and lower are not supported. Please update.");
}
- // default client version, higher versions check will be added
unsigned client_version = 1;
+ if (trezor_version >= pack_version(2, 3, 1)){
+ client_version = 3;
+ }
#ifdef WITH_TREZOR_DEBUGGING
// Override client version for tests
diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp
index 52bee6c6c..494706373 100644
--- a/src/device_trezor/trezor/transport.cpp
+++ b/src/device_trezor/trezor/transport.cpp
@@ -32,6 +32,7 @@
#endif
#include <algorithm>
+#include <functional>
#include <boost/endian/conversion.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
@@ -711,7 +712,7 @@ namespace trezor{
// Start the asynchronous operation itself. The handle_receive function
// used as a callback will update the ec and length variables.
m_socket->async_receive_from(boost::asio::buffer(buffer), m_endpoint,
- boost::bind(&UdpTransport::handle_receive, _1, _2, &ec, &length));
+ std::bind(&UdpTransport::handle_receive, std::placeholders::_1, std::placeholders::_2, &ec, &length));
// Block until the asynchronous operation has completed.
do {
diff --git a/src/mnemonics/language_base.h b/src/mnemonics/language_base.h
index 7d2599e9a..ad09dc5fa 100644
--- a/src/mnemonics/language_base.h
+++ b/src/mnemonics/language_base.h
@@ -41,6 +41,7 @@
#include <boost/algorithm/string.hpp>
#include "misc_log_ex.h"
#include "fnv1.h"
+#include "common/utf8.h"
/*!
* \namespace Language
@@ -73,78 +74,11 @@ namespace Language
return prefix;
}
- template<typename T>
- inline T utf8canonical(const T &s)
- {
- T sc = "";
- size_t avail = s.size();
- const char *ptr = s.data();
- wint_t cp = 0;
- int bytes = 1;
- char wbuf[8], *wptr;
- while (avail--)
- {
- if ((*ptr & 0x80) == 0)
- {
- cp = *ptr++;
- bytes = 1;
- }
- else if ((*ptr & 0xe0) == 0xc0)
- {
- if (avail < 1)
- throw std::runtime_error("Invalid UTF-8");
- cp = (*ptr++ & 0x1f) << 6;
- cp |= *ptr++ & 0x3f;
- --avail;
- bytes = 2;
- }
- else if ((*ptr & 0xf0) == 0xe0)
- {
- if (avail < 2)
- throw std::runtime_error("Invalid UTF-8");
- cp = (*ptr++ & 0xf) << 12;
- cp |= (*ptr++ & 0x3f) << 6;
- cp |= *ptr++ & 0x3f;
- avail -= 2;
- bytes = 3;
- }
- else if ((*ptr & 0xf8) == 0xf0)
- {
- if (avail < 3)
- throw std::runtime_error("Invalid UTF-8");
- cp = (*ptr++ & 0x7) << 18;
- cp |= (*ptr++ & 0x3f) << 12;
- cp |= (*ptr++ & 0x3f) << 6;
- cp |= *ptr++ & 0x3f;
- avail -= 3;
- bytes = 4;
- }
- else
- throw std::runtime_error("Invalid UTF-8");
-
- cp = std::towlower(cp);
- wptr = wbuf;
- switch (bytes)
- {
- case 1: *wptr++ = cp; break;
- case 2: *wptr++ = 0xc0 | (cp >> 6); *wptr++ = 0x80 | (cp & 0x3f); break;
- case 3: *wptr++ = 0xe0 | (cp >> 12); *wptr++ = 0x80 | ((cp >> 6) & 0x3f); *wptr++ = 0x80 | (cp & 0x3f); break;
- case 4: *wptr++ = 0xf0 | (cp >> 18); *wptr++ = 0x80 | ((cp >> 12) & 0x3f); *wptr++ = 0x80 | ((cp >> 6) & 0x3f); *wptr++ = 0x80 | (cp & 0x3f); break;
- default: throw std::runtime_error("Invalid UTF-8");
- }
- *wptr = 0;
- sc += T(wbuf, bytes);
- cp = 0;
- bytes = 1;
- }
- return sc;
- }
-
struct WordHash
{
std::size_t operator()(const epee::wipeable_string &s) const
{
- const epee::wipeable_string sc = utf8canonical(s);
+ const epee::wipeable_string sc = tools::utf8canonical(s, [](wint_t c) -> wint_t { return std::towlower(c); });
return epee::fnv::FNV1a(sc.data(), sc.size());
}
};
@@ -153,8 +87,8 @@ namespace Language
{
bool operator()(const epee::wipeable_string &s0, const epee::wipeable_string &s1) const
{
- const epee::wipeable_string s0c = utf8canonical(s0);
- const epee::wipeable_string s1c = utf8canonical(s1);
+ const epee::wipeable_string s0c = tools::utf8canonical(s0, [](wint_t c) -> wint_t { return std::towlower(c); });
+ const epee::wipeable_string s1c = tools::utf8canonical(s1, [](wint_t c) -> wint_t { return std::towlower(c); });
return s0c == s1c;
}
};
diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp
index 999894db0..70a4c1c8e 100644
--- a/src/multisig/multisig.cpp
+++ b/src/multisig/multisig.cpp
@@ -82,6 +82,7 @@ namespace cryptonote
{
rct::key sk = rct::scalarmultKey(rct::pk2rct(k), rct::sk2rct(blinded_skey));
crypto::secret_key msk = get_multisig_blinded_secret_key(rct::rct2sk(sk));
+ memwipe(&sk, sizeof(sk));
multisig_keys.push_back(msk);
sc_add(spend_skey.bytes, spend_skey.bytes, (const unsigned char*)msk.data);
}
@@ -126,10 +127,10 @@ namespace cryptonote
//-----------------------------------------------------------------
crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector<crypto::secret_key> &skeys)
{
- rct::key view_skey = rct::sk2rct(get_multisig_blinded_secret_key(skey));
+ crypto::secret_key view_skey = get_multisig_blinded_secret_key(skey);
for (const auto &k: skeys)
- sc_add(view_skey.bytes, view_skey.bytes, rct::sk2rct(k).bytes);
- return rct::rct2sk(view_skey);
+ sc_add((unsigned char*)&view_skey, rct::sk2rct(view_skey).bytes, rct::sk2rct(k).bytes);
+ return view_skey;
}
//-----------------------------------------------------------------
crypto::public_key generate_multisig_M_N_spend_public_key(const std::vector<crypto::public_key> &pkeys)
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 2d7600f7a..5bd845e4f 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -31,7 +31,7 @@
// IP blocking adapted from Boolberry
#include <algorithm>
-#include <boost/bind.hpp>
+#include <boost/bind/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/optional/optional.hpp>
@@ -632,6 +632,9 @@ namespace nodetool
full_addrs.insert("192.110.160.146:18080");
full_addrs.insert("88.198.163.90:18080");
full_addrs.insert("95.217.25.101:18080");
+ full_addrs.insert("209.250.243.248:18080");
+ full_addrs.insert("104.238.221.81:18080");
+ full_addrs.insert("66.85.74.134:18080");
}
return full_addrs;
}
diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc
index 2ff88c6e7..6b88fd730 100644
--- a/src/ringct/bulletproofs.cc
+++ b/src/ringct/bulletproofs.cc
@@ -905,7 +905,7 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
rct::key m_y0 = rct::zero(), y1 = rct::zero();
int proof_data_index = 0;
rct::keyV w_cache;
- rct::keyV proof8_V, proof8_L, proof8_R;
+ std::vector<ge_p3> proof8_V, proof8_L, proof8_R;
for (const Bulletproof *p: proofs)
{
const Bulletproof &proof = *p;
@@ -918,13 +918,17 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
const rct::key weight_z = rct::skGen();
// pre-multiply some points by 8
- proof8_V.resize(proof.V.size()); for (size_t i = 0; i < proof.V.size(); ++i) proof8_V[i] = rct::scalarmult8(proof.V[i]);
- proof8_L.resize(proof.L.size()); for (size_t i = 0; i < proof.L.size(); ++i) proof8_L[i] = rct::scalarmult8(proof.L[i]);
- proof8_R.resize(proof.R.size()); for (size_t i = 0; i < proof.R.size(); ++i) proof8_R[i] = rct::scalarmult8(proof.R[i]);
- rct::key proof8_T1 = rct::scalarmult8(proof.T1);
- rct::key proof8_T2 = rct::scalarmult8(proof.T2);
- rct::key proof8_S = rct::scalarmult8(proof.S);
- rct::key proof8_A = rct::scalarmult8(proof.A);
+ proof8_V.resize(proof.V.size()); for (size_t i = 0; i < proof.V.size(); ++i) rct::scalarmult8(proof8_V[i], proof.V[i]);
+ proof8_L.resize(proof.L.size()); for (size_t i = 0; i < proof.L.size(); ++i) rct::scalarmult8(proof8_L[i], proof.L[i]);
+ proof8_R.resize(proof.R.size()); for (size_t i = 0; i < proof.R.size(); ++i) rct::scalarmult8(proof8_R[i], proof.R[i]);
+ ge_p3 proof8_T1;
+ ge_p3 proof8_T2;
+ ge_p3 proof8_S;
+ ge_p3 proof8_A;
+ rct::scalarmult8(proof8_T1, proof.T1);
+ rct::scalarmult8(proof8_T2, proof.T2);
+ rct::scalarmult8(proof8_S, proof.S);
+ rct::scalarmult8(proof8_A, proof.A);
PERF_TIMER_START_BP(VERIFY_line_61);
sc_mulsub(m_y0.bytes, proof.taux.bytes, weight_y.bytes, m_y0.bytes);
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index 6e4d063df..b2dd32ada 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -408,6 +408,18 @@ namespace rct {
return res;
}
+ //Computes 8P without byte conversion
+ void scalarmult8(ge_p3 &res, const key &P)
+ {
+ ge_p3 p3;
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&p3, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ ge_p2 p2;
+ ge_p3_to_p2(&p2, &p3);
+ ge_p1p1 p1;
+ ge_mul8(&p1, &p2);
+ ge_p1p1_to_p3(&res, &p1);
+ }
+
//Computes lA where l is the curve order
bool isInMainSubgroup(const key & A) {
ge_p3 p3;
diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h
index c24d48e9a..74e0ad833 100644
--- a/src/ringct/rctOps.h
+++ b/src/ringct/rctOps.h
@@ -124,6 +124,7 @@ namespace rct {
key scalarmultH(const key & a);
// multiplies a point by 8
key scalarmult8(const key & P);
+ void scalarmult8(ge_p3 &res, const key & P);
// checks a is in the main subgroup (ie, not a small one)
bool isInMainSubgroup(const key & a);
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index a7b265d63..2e3e7007e 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -29,6 +29,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "misc_log_ex.h"
+#include "misc_language.h"
#include "common/perf_timer.h"
#include "common/threadpool.h"
#include "common/util.h"
@@ -108,6 +109,7 @@ namespace rct {
//Borromean (c.f. gmax/andytoshi's paper)
boroSig genBorromean(const key64 x, const key64 P1, const key64 P2, const bits indices) {
key64 L[2], alpha;
+ auto wiper = epee::misc_utils::create_scope_leave_handler([&](){memwipe(alpha, sizeof(alpha));});
key c;
int naught = 0, prime = 0, ii = 0, jj=0;
boroSig bb;
@@ -190,6 +192,7 @@ namespace rct {
vector<geDsmp> Ip(dsRows);
rv.II = keyV(dsRows);
keyV alpha(rows);
+ auto wiper = epee::misc_utils::create_scope_leave_handler([&](){memwipe(alpha.data(), alpha.size() * sizeof(alpha[0]));});
keyV aG(rows);
rv.ss = keyM(cols, aG);
keyV aHP(dsRows);
@@ -548,7 +551,7 @@ namespace rct {
subKeys(M[i][1], pubs[i].mask, Cout);
}
mgSig result = MLSAG_Gen(message, M, sk, kLRki, mscout, index, rows, hwdev);
- memwipe(&sk[0], sizeof(key));
+ memwipe(sk.data(), sk.size() * sizeof(key));
return result;
}
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index bf4b7b4aa..9b7f26a02 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -48,6 +48,7 @@ extern "C" {
#include "hex.h"
#include "span.h"
+#include "memwipe.h"
#include "serialization/vector.h"
#include "serialization/debug_archive.h"
#include "serialization/binary_archive.h"
@@ -106,6 +107,8 @@ namespace rct {
key L;
key R;
key ki;
+
+ ~multisig_kLRki() { memwipe(&k, sizeof(k)); }
};
struct multisig_out {
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index a789a7a1a..3807d73d9 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -68,6 +68,11 @@ using namespace epee;
#define DEFAULT_PAYMENT_DIFFICULTY 1000
#define DEFAULT_PAYMENT_CREDITS_PER_HASH 100
+#define RESTRICTED_BLOCK_HEADER_RANGE 1000
+#define RESTRICTED_TRANSACTIONS_COUNT 100
+#define RESTRICTED_SPENT_KEY_IMAGES_COUNT 5000
+#define RESTRICTED_BLOCK_COUNT 1000
+
#define RPC_TRACKER(rpc) \
PERF_TIMER(rpc); \
RPCTracker tracker(#rpc, PERF_TIMER_NAME(rpc))
@@ -265,25 +270,25 @@ namespace cryptonote
{
if (!m_restricted && nettype() != FAKECHAIN)
{
- MERROR("RPC payment enabled, but server is not restricted, anyone can adjust their balance to bypass payment");
+ MFATAL("RPC payment enabled, but server is not restricted, anyone can adjust their balance to bypass payment");
return false;
}
cryptonote::address_parse_info info;
if (!get_account_address_from_str(info, nettype(), address))
{
- MERROR("Invalid payment address: " << address);
+ MFATAL("Invalid payment address: " << address);
return false;
}
if (info.is_subaddress)
{
- MERROR("Payment address may not be a subaddress: " << address);
+ MFATAL("Payment address may not be a subaddress: " << address);
return false;
}
uint64_t diff = command_line::get_arg(vm, arg_rpc_payment_difficulty);
uint64_t credits = command_line::get_arg(vm, arg_rpc_payment_credits);
if (diff == 0 || credits == 0)
{
- MERROR("Payments difficulty and/or payments credits are 0, but a payment address was given");
+ MFATAL("Payments difficulty and/or payments credits are 0, but a payment address was given");
return false;
}
m_rpc_payment_allow_free_loopback = command_line::get_arg(vm, arg_rpc_payment_allow_free_loopback);
@@ -303,7 +308,7 @@ namespace cryptonote
if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
command_line::get_arg(vm, arg_bootstrap_daemon_login)))
{
- MERROR("Failed to parse bootstrap daemon address");
+ MFATAL("Failed to parse bootstrap daemon address");
return false;
}
@@ -639,6 +644,13 @@ namespace cryptonote
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_BY_HEIGHT>(invoke_http_mode::BIN, "/getblocks_by_height.bin", req, res, r))
return r;
+ const bool restricted = m_restricted && ctx;
+ if (restricted && req.heights.size() > RESTRICTED_BLOCK_COUNT)
+ {
+ res.status = "Too many blocks requested in restricted mode";
+ return true;
+ }
+
res.status = "Failed";
res.blocks.clear();
res.blocks.reserve(req.heights.size());
@@ -793,11 +805,17 @@ namespace cryptonote
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTIONS>(invoke_http_mode::JON, "/gettransactions", req, res, ok))
return ok;
- CHECK_PAYMENT_MIN1(req, res, req.txs_hashes.size() * COST_PER_TX, false);
-
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
+ if (restricted && req.txs_hashes.size() > RESTRICTED_TRANSACTIONS_COUNT)
+ {
+ res.status = "Too many transactions requested in restricted mode";
+ return true;
+ }
+
+ CHECK_PAYMENT_MIN1(req, res, req.txs_hashes.size() * COST_PER_TX, false);
+
std::vector<crypto::hash> vh;
for(const auto& tx_hex_str: req.txs_hashes)
{
@@ -1027,11 +1045,17 @@ namespace cryptonote
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_IS_KEY_IMAGE_SPENT>(invoke_http_mode::JON, "/is_key_image_spent", req, res, ok))
return ok;
- CHECK_PAYMENT_MIN1(req, res, req.key_images.size() * COST_PER_KEY_IMAGE, false);
-
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
+ if (restricted && req.key_images.size() > RESTRICTED_SPENT_KEY_IMAGES_COUNT)
+ {
+ res.status = "Too many key images queried in restricted mode";
+ return true;
+ }
+
+ CHECK_PAYMENT_MIN1(req, res, req.key_images.size() * COST_PER_KEY_IMAGE, false);
+
std::vector<crypto::key_image> key_images;
for(const auto& ki_hex_str: req.key_images)
{
@@ -1990,7 +2014,7 @@ namespace cryptonote
r = false;
}
res.untrusted = true;
- return true;
+ return r;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
@@ -2034,6 +2058,14 @@ namespace cryptonote
CHECK_PAYMENT_MIN1(req, res, COST_PER_BLOCK_HEADER, false);
+ const bool restricted = m_restricted && ctx;
+ if (restricted && req.hashes.size() > RESTRICTED_BLOCK_COUNT)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_RESTRICTED;
+ error_resp.message = "Too many block headers requested in restricted mode";
+ return false;
+ }
+
auto get = [this](const std::string &hash, bool fill_pow_hash, block_header_response &block_header, bool restricted, epee::json_rpc::error& error_resp) -> bool {
crypto::hash block_hash;
bool hash_parsed = parse_hash256(hash, block_hash);
@@ -2069,7 +2101,6 @@ namespace cryptonote
return true;
};
- const bool restricted = m_restricted && ctx;
if (!req.hash.empty())
{
if (!get(req.hash, req.fill_pow_hash, res.block_header, restricted, error_resp))
@@ -2101,6 +2132,14 @@ namespace cryptonote
error_resp.message = "Invalid start/end heights.";
return false;
}
+ const bool restricted = m_restricted && ctx;
+ if (restricted && req.end_height - req.start_height > RESTRICTED_BLOCK_HEADER_RANGE)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_RESTRICTED;
+ error_resp.message = "Too many block headers requested.";
+ return false;
+ }
+
CHECK_PAYMENT_MIN1(req, res, (req.end_height - req.start_height + 1) * COST_PER_BLOCK_HEADER, false);
for (uint64_t h = req.start_height; h <= req.end_height; ++h)
{
@@ -2127,7 +2166,6 @@ namespace cryptonote
return false;
}
res.headers.push_back(block_header_response());
- const bool restricted = m_restricted && ctx;
bool response_filled = fill_block_header_response(blk, false, block_height, block_hash, res.headers.back(), req.fill_pow_hash && !restricted);
if (!response_filled)
{
@@ -2778,7 +2816,7 @@ namespace cryptonote
crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
cryptonote::blobdata txblob;
- if (!m_core.get_pool_transaction(txid, txblob, relay_category::legacy))
+ if (m_core.get_pool_transaction(txid, txblob, relay_category::legacy))
{
NOTIFY_NEW_TRANSACTIONS::request r;
r.txs.push_back(std::move(txblob));
diff --git a/src/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h
index 2fd42f43f..98e40d05f 100644
--- a/src/rpc/core_rpc_server_error_codes.h
+++ b/src/rpc/core_rpc_server_error_codes.h
@@ -48,6 +48,7 @@
#define CORE_RPC_ERROR_CODE_PAYMENT_TOO_LOW -16
#define CORE_RPC_ERROR_CODE_DUPLICATE_PAYMENT -17
#define CORE_RPC_ERROR_CODE_STALE_PAYMENT -18
+#define CORE_RPC_ERROR_CODE_RESTRICTED -19
static inline const char *get_rpc_server_error_message(int64_t code)
{
@@ -70,6 +71,7 @@ static inline const char *get_rpc_server_error_message(int64_t code)
case CORE_RPC_ERROR_CODE_PAYMENT_TOO_LOW: return "Payment too low";
case CORE_RPC_ERROR_CODE_DUPLICATE_PAYMENT: return "Duplicate payment";
case CORE_RPC_ERROR_CODE_STALE_PAYMENT: return "Stale payment";
+ case CORE_RPC_ERROR_CODE_RESTRICTED: return "Parameters beyond restricted allowance";
default: MERROR("Unknown error: " << code); return "Unknown error";
}
}
diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp
index de0510fec..1aad82159 100644
--- a/src/rpc/daemon_handler.cpp
+++ b/src/rpc/daemon_handler.cpp
@@ -101,7 +101,8 @@ namespace rpc
{u8"key_images_spent", handle_message<KeyImagesSpent>},
{u8"mining_status", handle_message<MiningStatus>},
{u8"save_bc", handle_message<SaveBC>},
- {u8"send_raw_tx", handle_message<SendRawTxHex>},
+ {u8"send_raw_tx", handle_message<SendRawTx>},
+ {u8"send_raw_tx_hex", handle_message<SendRawTxHex>},
{u8"set_log_level", handle_message<SetLogLevel>},
{u8"start_mining", handle_message<StartMining>},
{u8"stop_mining", handle_message<StopMining>}
diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp
index 5c179408e..22f73472d 100644
--- a/src/rpc/daemon_messages.cpp
+++ b/src/rpc/daemon_messages.cpp
@@ -34,14 +34,14 @@ namespace cryptonote
namespace rpc
{
-void GetHeight::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetHeight::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void GetHeight::Request::fromJson(const rapidjson::Value& val)
{
}
-void GetHeight::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetHeight::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, height, height);
}
@@ -52,7 +52,7 @@ void GetHeight::Response::fromJson(const rapidjson::Value& val)
}
-void GetBlocksFast::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlocksFast::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, block_ids, block_ids);
INSERT_INTO_JSON_OBJECT(dest, start_height, start_height);
@@ -66,7 +66,7 @@ void GetBlocksFast::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, prune, prune);
}
-void GetBlocksFast::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlocksFast::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, blocks, blocks);
INSERT_INTO_JSON_OBJECT(dest, start_height, start_height);
@@ -83,7 +83,7 @@ void GetBlocksFast::Response::fromJson(const rapidjson::Value& val)
}
-void GetHashesFast::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetHashesFast::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, known_hashes, known_hashes);
INSERT_INTO_JSON_OBJECT(dest, start_height, start_height);
@@ -95,7 +95,7 @@ void GetHashesFast::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, start_height, start_height);
}
-void GetHashesFast::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetHashesFast::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, hashes, hashes);
INSERT_INTO_JSON_OBJECT(dest, start_height, start_height);
@@ -110,7 +110,7 @@ void GetHashesFast::Response::fromJson(const rapidjson::Value& val)
}
-void GetTransactions::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetTransactions::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, tx_hashes, tx_hashes);
}
@@ -120,7 +120,7 @@ void GetTransactions::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, tx_hashes, tx_hashes);
}
-void GetTransactions::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetTransactions::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, txs, txs);
INSERT_INTO_JSON_OBJECT(dest, missed_hashes, missed_hashes);
@@ -133,7 +133,7 @@ void GetTransactions::Response::fromJson(const rapidjson::Value& val)
}
-void KeyImagesSpent::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void KeyImagesSpent::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, key_images, key_images);
}
@@ -143,7 +143,7 @@ void KeyImagesSpent::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, key_images, key_images);
}
-void KeyImagesSpent::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void KeyImagesSpent::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, spent_status, spent_status);
}
@@ -154,7 +154,7 @@ void KeyImagesSpent::Response::fromJson(const rapidjson::Value& val)
}
-void GetTxGlobalOutputIndices::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetTxGlobalOutputIndices::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, tx_hash, tx_hash);
}
@@ -164,7 +164,7 @@ void GetTxGlobalOutputIndices::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, tx_hash, tx_hash);
}
-void GetTxGlobalOutputIndices::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetTxGlobalOutputIndices::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, output_indices, output_indices);
}
@@ -174,7 +174,7 @@ void GetTxGlobalOutputIndices::Response::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, output_indices, output_indices);
}
-void SendRawTx::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SendRawTx::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, tx, tx);
INSERT_INTO_JSON_OBJECT(dest, relay, relay);
@@ -186,7 +186,7 @@ void SendRawTx::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, relay, relay);
}
-void SendRawTx::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SendRawTx::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, relayed, relayed);
}
@@ -197,7 +197,7 @@ void SendRawTx::Response::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, relayed, relayed);
}
-void SendRawTxHex::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SendRawTxHex::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, tx_as_hex, tx_as_hex);
INSERT_INTO_JSON_OBJECT(dest, relay, relay);
@@ -209,7 +209,7 @@ void SendRawTxHex::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, relay, relay);
}
-void StartMining::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void StartMining::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, miner_address, miner_address);
INSERT_INTO_JSON_OBJECT(dest, threads_count, threads_count);
@@ -225,7 +225,7 @@ void StartMining::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, ignore_battery, ignore_battery);
}
-void StartMining::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void StartMining::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void StartMining::Response::fromJson(const rapidjson::Value& val)
@@ -233,14 +233,14 @@ void StartMining::Response::fromJson(const rapidjson::Value& val)
}
-void StopMining::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void StopMining::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void StopMining::Request::fromJson(const rapidjson::Value& val)
{
}
-void StopMining::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void StopMining::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void StopMining::Response::fromJson(const rapidjson::Value& val)
@@ -248,14 +248,14 @@ void StopMining::Response::fromJson(const rapidjson::Value& val)
}
-void MiningStatus::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void MiningStatus::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void MiningStatus::Request::fromJson(const rapidjson::Value& val)
{
}
-void MiningStatus::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void MiningStatus::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, active, active);
INSERT_INTO_JSON_OBJECT(dest, speed, speed);
@@ -274,14 +274,14 @@ void MiningStatus::Response::fromJson(const rapidjson::Value& val)
}
-void GetInfo::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetInfo::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void GetInfo::Request::fromJson(const rapidjson::Value& val)
{
}
-void GetInfo::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetInfo::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, info, info);
}
@@ -292,14 +292,14 @@ void GetInfo::Response::fromJson(const rapidjson::Value& val)
}
-void SaveBC::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SaveBC::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void SaveBC::Request::fromJson(const rapidjson::Value& val)
{
}
-void SaveBC::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SaveBC::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void SaveBC::Response::fromJson(const rapidjson::Value& val)
@@ -307,7 +307,7 @@ void SaveBC::Response::fromJson(const rapidjson::Value& val)
}
-void GetBlockHash::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHash::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, height, height);
}
@@ -317,7 +317,7 @@ void GetBlockHash::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, height, height);
}
-void GetBlockHash::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHash::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, hash, hash);
}
@@ -328,14 +328,14 @@ void GetBlockHash::Response::fromJson(const rapidjson::Value& val)
}
-void GetLastBlockHeader::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetLastBlockHeader::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void GetLastBlockHeader::Request::fromJson(const rapidjson::Value& val)
{
}
-void GetLastBlockHeader::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetLastBlockHeader::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, header, header);
}
@@ -346,7 +346,7 @@ void GetLastBlockHeader::Response::fromJson(const rapidjson::Value& val)
}
-void GetBlockHeaderByHash::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHeaderByHash::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, hash, hash);
}
@@ -356,7 +356,7 @@ void GetBlockHeaderByHash::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, hash, hash);
}
-void GetBlockHeaderByHash::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHeaderByHash::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, header, header);
}
@@ -367,7 +367,7 @@ void GetBlockHeaderByHash::Response::fromJson(const rapidjson::Value& val)
}
-void GetBlockHeaderByHeight::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHeaderByHeight::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, height, height);
}
@@ -377,7 +377,7 @@ void GetBlockHeaderByHeight::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, height, height);
}
-void GetBlockHeaderByHeight::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHeaderByHeight::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, header, header);
}
@@ -388,7 +388,7 @@ void GetBlockHeaderByHeight::Response::fromJson(const rapidjson::Value& val)
}
-void GetBlockHeadersByHeight::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHeadersByHeight::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, heights, heights);
}
@@ -398,7 +398,7 @@ void GetBlockHeadersByHeight::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, heights, heights);
}
-void GetBlockHeadersByHeight::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetBlockHeadersByHeight::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, headers, headers);
}
@@ -409,14 +409,14 @@ void GetBlockHeadersByHeight::Response::fromJson(const rapidjson::Value& val)
}
-void GetPeerList::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetPeerList::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void GetPeerList::Request::fromJson(const rapidjson::Value& val)
{
}
-void GetPeerList::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetPeerList::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, white_list, white_list);
INSERT_INTO_JSON_OBJECT(dest, gray_list, gray_list);
@@ -429,7 +429,7 @@ void GetPeerList::Response::fromJson(const rapidjson::Value& val)
}
-void SetLogLevel::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SetLogLevel::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, level, level);
}
@@ -439,7 +439,7 @@ void SetLogLevel::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, level, level);
}
-void SetLogLevel::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void SetLogLevel::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void SetLogLevel::Response::fromJson(const rapidjson::Value& val)
@@ -447,14 +447,14 @@ void SetLogLevel::Response::fromJson(const rapidjson::Value& val)
}
-void GetTransactionPool::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetTransactionPool::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void GetTransactionPool::Request::fromJson(const rapidjson::Value& val)
{
}
-void GetTransactionPool::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetTransactionPool::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, transactions, transactions);
INSERT_INTO_JSON_OBJECT(dest, key_images, key_images);
@@ -467,7 +467,7 @@ void GetTransactionPool::Response::fromJson(const rapidjson::Value& val)
}
-void HardForkInfo::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void HardForkInfo::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, version, version);
}
@@ -477,7 +477,7 @@ void HardForkInfo::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, version, version);
}
-void HardForkInfo::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void HardForkInfo::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, info, info);
}
@@ -488,7 +488,7 @@ void HardForkInfo::Response::fromJson(const rapidjson::Value& val)
}
-void GetOutputHistogram::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetOutputHistogram::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, amounts, amounts);
INSERT_INTO_JSON_OBJECT(dest, min_count, min_count);
@@ -506,7 +506,7 @@ void GetOutputHistogram::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, recent_cutoff, recent_cutoff);
}
-void GetOutputHistogram::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetOutputHistogram::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, histogram, histogram);
}
@@ -517,7 +517,7 @@ void GetOutputHistogram::Response::fromJson(const rapidjson::Value& val)
}
-void GetOutputKeys::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetOutputKeys::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, outputs, outputs);
}
@@ -527,7 +527,7 @@ void GetOutputKeys::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, outputs, outputs);
}
-void GetOutputKeys::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetOutputKeys::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, keys, keys);
}
@@ -538,14 +538,14 @@ void GetOutputKeys::Response::fromJson(const rapidjson::Value& val)
}
-void GetRPCVersion::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetRPCVersion::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
void GetRPCVersion::Request::fromJson(const rapidjson::Value& val)
{
}
-void GetRPCVersion::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetRPCVersion::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, version, version);
}
@@ -555,7 +555,7 @@ void GetRPCVersion::Response::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, version, version);
}
-void GetFeeEstimate::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetFeeEstimate::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, num_grace_blocks, num_grace_blocks);
}
@@ -565,7 +565,7 @@ void GetFeeEstimate::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, num_grace_blocks, num_grace_blocks);
}
-void GetFeeEstimate::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetFeeEstimate::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, estimated_base_fee, estimated_base_fee);
INSERT_INTO_JSON_OBJECT(dest, fee_mask, fee_mask);
@@ -581,7 +581,7 @@ void GetFeeEstimate::Response::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, hard_fork_version, hard_fork_version);
}
-void GetOutputDistribution::Request::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetOutputDistribution::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, amounts, amounts);
INSERT_INTO_JSON_OBJECT(dest, from_height, from_height);
@@ -597,7 +597,7 @@ void GetOutputDistribution::Request::fromJson(const rapidjson::Value& val)
GET_FROM_JSON_OBJECT(val, cumulative, cumulative);
}
-void GetOutputDistribution::Response::doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void GetOutputDistribution::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
INSERT_INTO_JSON_OBJECT(dest, status, status);
INSERT_INTO_JSON_OBJECT(dest, distributions, distributions);
diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h
index bb5059cdc..64ea3e9d4 100644
--- a/src/rpc/daemon_messages.h
+++ b/src/rpc/daemon_messages.h
@@ -28,11 +28,11 @@
#pragma once
-#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <unordered_map>
#include <vector>
+#include "byte_stream.h"
#include "message.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "rpc/message_data_structs.h"
@@ -50,7 +50,7 @@ class classname \
public: \
Request() { } \
~Request() { } \
- void doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const override final; \
+ void doToJson(rapidjson::Writer<epee::byte_stream>& dest) const override final; \
void fromJson(const rapidjson::Value& val) override final;
#define BEGIN_RPC_MESSAGE_RESPONSE \
@@ -59,7 +59,7 @@ class classname \
public: \
Response() { } \
~Response() { } \
- void doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const override final; \
+ void doToJson(rapidjson::Writer<epee::byte_stream>& dest) const override final; \
void fromJson(const rapidjson::Value& val) override final;
#define END_RPC_MESSAGE_REQUEST };
diff --git a/src/rpc/message.cpp b/src/rpc/message.cpp
index 0d8983cb1..fffb44921 100644
--- a/src/rpc/message.cpp
+++ b/src/rpc/message.cpp
@@ -62,7 +62,7 @@ const rapidjson::Value& get_method_field(const rapidjson::Value& src)
}
}
-void Message::toJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+void Message::toJson(rapidjson::Writer<epee::byte_stream>& dest) const
{
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, status, status);
@@ -151,9 +151,9 @@ cryptonote::rpc::error FullMessage::getError()
epee::byte_slice FullMessage::getRequest(const std::string& request, const Message& message, const unsigned id)
{
- rapidjson::StringBuffer buffer;
+ epee::byte_stream buffer;
{
- rapidjson::Writer<rapidjson::StringBuffer> dest{buffer};
+ rapidjson::Writer<epee::byte_stream> dest{buffer};
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, jsonrpc, (boost::string_ref{"2.0", 3}));
@@ -172,15 +172,15 @@ epee::byte_slice FullMessage::getRequest(const std::string& request, const Messa
if (!dest.IsComplete())
throw std::logic_error{"Invalid JSON tree generated"};
}
- return epee::byte_slice{{buffer.GetString(), buffer.GetSize()}};
+ return epee::byte_slice{std::move(buffer)};
}
epee::byte_slice FullMessage::getResponse(const Message& message, const rapidjson::Value& id)
{
- rapidjson::StringBuffer buffer;
+ epee::byte_stream buffer;
{
- rapidjson::Writer<rapidjson::StringBuffer> dest{buffer};
+ rapidjson::Writer<epee::byte_stream> dest{buffer};
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, jsonrpc, (boost::string_ref{"2.0", 3}));
@@ -207,7 +207,7 @@ epee::byte_slice FullMessage::getResponse(const Message& message, const rapidjso
if (!dest.IsComplete())
throw std::logic_error{"Invalid JSON tree generated"};
}
- return epee::byte_slice{{buffer.GetString(), buffer.GetSize()}};
+ return epee::byte_slice{std::move(buffer)};
}
// convenience functions for bad input
diff --git a/src/rpc/message.h b/src/rpc/message.h
index 8156e232c..5c369cdfc 100644
--- a/src/rpc/message.h
+++ b/src/rpc/message.h
@@ -29,11 +29,11 @@
#pragma once
#include <rapidjson/document.h>
-#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <string>
#include "byte_slice.h"
+#include "byte_stream.h"
#include "rpc/message_data_structs.h"
namespace cryptonote
@@ -44,7 +44,7 @@ namespace rpc
class Message
{
- virtual void doToJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const
+ virtual void doToJson(rapidjson::Writer<epee::byte_stream>& dest) const
{}
public:
@@ -58,7 +58,7 @@ namespace rpc
virtual ~Message() { }
- void toJson(rapidjson::Writer<rapidjson::StringBuffer>& dest) const;
+ void toJson(rapidjson::Writer<epee::byte_stream>& dest) const;
virtual void fromJson(const rapidjson::Value& val);
diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
index 9153e76ea..8601bd0b4 100644
--- a/src/rpc/rpc_args.cpp
+++ b/src/rpc/rpc_args.cpp
@@ -30,7 +30,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/asio/ip/address.hpp>
-#include <boost/bind.hpp>
+#include <functional>
#include "common/command_line.h"
#include "common/i18n.h"
#include "hex.h"
@@ -221,7 +221,7 @@ namespace cryptonote
std::vector<std::string> access_control_origins;
boost::split(access_control_origins, access_control_origins_input, boost::is_any_of(","));
- std::for_each(access_control_origins.begin(), access_control_origins.end(), boost::bind(&boost::trim<std::string>, _1, std::locale::classic()));
+ std::for_each(access_control_origins.begin(), access_control_origins.end(), std::bind(&boost::trim<std::string>, std::placeholders::_1, std::locale::classic()));
config.access_control_origins = std::move(access_control_origins);
}
diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp
index 2b9c19f57..6ff3ff525 100644
--- a/src/rpc/rpc_payment.cpp
+++ b/src/rpc/rpc_payment.cpp
@@ -92,6 +92,7 @@ namespace cryptonote
uint64_t rpc_payment::balance(const crypto::public_key &client, int64_t delta)
{
+ boost::lock_guard<boost::mutex> lock(mutex);
client_info &info = m_client_info[client]; // creates if not found
uint64_t credits = info.credits;
if (delta > 0 && credits > std::numeric_limits<uint64_t>::max() - delta)
@@ -107,6 +108,7 @@ namespace cryptonote
bool rpc_payment::pay(const crypto::public_key &client, uint64_t ts, uint64_t payment, const std::string &rpc, bool same_ts, uint64_t &credits)
{
+ boost::lock_guard<boost::mutex> lock(mutex);
client_info &info = m_client_info[client]; // creates if not found
if (ts < info.last_request_timestamp || (ts == info.last_request_timestamp && !same_ts))
{
@@ -130,6 +132,7 @@ namespace cryptonote
bool rpc_payment::get_info(const crypto::public_key &client, const std::function<bool(const cryptonote::blobdata&, cryptonote::block&, uint64_t &seed_height, crypto::hash &seed_hash)> &get_block_template, cryptonote::blobdata &hashing_blob, uint64_t &seed_height, crypto::hash &seed_hash, const crypto::hash &top, uint64_t &diff, uint64_t &credits_per_hash_found, uint64_t &credits, uint32_t &cookie)
{
+ boost::lock_guard<boost::mutex> lock(mutex);
client_info &info = m_client_info[client]; // creates if not found
const uint64_t now = time(NULL);
bool need_template = top != info.top || now >= info.block_template_update_time + STALE_THRESHOLD;
@@ -180,6 +183,7 @@ namespace cryptonote
bool rpc_payment::submit_nonce(const crypto::public_key &client, uint32_t nonce, const crypto::hash &top, int64_t &error_code, std::string &error_message, uint64_t &credits, crypto::hash &hash, cryptonote::block &block, uint32_t cookie, bool &stale)
{
+ boost::lock_guard<boost::mutex> lock(mutex);
client_info &info = m_client_info[client]; // creates if not found
if (cookie != info.cookie && cookie != info.cookie - 1)
{
@@ -272,6 +276,7 @@ namespace cryptonote
bool rpc_payment::foreach(const std::function<bool(const crypto::public_key &client, const client_info &info)> &f) const
{
+ boost::lock_guard<boost::mutex> lock(mutex);
for (std::unordered_map<crypto::public_key, client_info>::const_iterator i = m_client_info.begin(); i != m_client_info.end(); ++i)
{
if (!f(i->first, i->second))
@@ -283,8 +288,9 @@ namespace cryptonote
bool rpc_payment::load(std::string directory)
{
TRY_ENTRY();
+ boost::lock_guard<boost::mutex> lock(mutex);
m_directory = std::move(directory);
- std::string state_file_path = directory + "/" + RPC_PAYMENTS_DATA_FILENAME;
+ std::string state_file_path = m_directory + "/" + RPC_PAYMENTS_DATA_FILENAME;
MINFO("loading rpc payments data from " << state_file_path);
std::ifstream data;
data.open(state_file_path, std::ios_base::binary | std::ios_base::in);
@@ -313,6 +319,7 @@ namespace cryptonote
bool rpc_payment::store(const std::string &directory_) const
{
TRY_ENTRY();
+ boost::lock_guard<boost::mutex> lock(mutex);
const std::string &directory = directory_.empty() ? m_directory : directory_;
MDEBUG("storing rpc payments data to " << directory);
if (!tools::create_directories_if_necessary(directory))
@@ -345,6 +352,7 @@ namespace cryptonote
unsigned int rpc_payment::flush_by_age(time_t seconds)
{
+ boost::lock_guard<boost::mutex> lock(mutex);
unsigned int count = 0;
const time_t now = time(NULL);
time_t seconds0 = seconds;
@@ -358,7 +366,7 @@ namespace cryptonote
for (std::unordered_map<crypto::public_key, client_info>::iterator i = m_client_info.begin(); i != m_client_info.end(); )
{
std::unordered_map<crypto::public_key, client_info>::iterator j = i++;
- const time_t t = std::max(j->second.last_request_timestamp, j->second.update_time);
+ const time_t t = std::max(j->second.last_request_timestamp / 1000000, j->second.update_time);
const bool erase = t < ((j->second.credits == 0) ? threshold0 : threshold);
if (erase)
{
@@ -372,6 +380,7 @@ namespace cryptonote
uint64_t rpc_payment::get_hashes(unsigned int seconds) const
{
+ boost::lock_guard<boost::mutex> lock(mutex);
const uint64_t now = time(NULL);
uint64_t hashes = 0;
for (std::map<uint64_t, uint64_t>::const_reverse_iterator i = m_hashrate.crbegin(); i != m_hashrate.crend(); ++i)
@@ -385,6 +394,7 @@ namespace cryptonote
void rpc_payment::prune_hashrate(unsigned int seconds)
{
+ boost::lock_guard<boost::mutex> lock(mutex);
const uint64_t now = time(NULL);
std::map<uint64_t, uint64_t>::iterator i;
for (i = m_hashrate.begin(); i != m_hashrate.end(); ++i)
diff --git a/src/rpc/rpc_payment.h b/src/rpc/rpc_payment.h
index f6832fd34..20117985f 100644
--- a/src/rpc/rpc_payment.h
+++ b/src/rpc/rpc_payment.h
@@ -31,6 +31,7 @@
#include <string>
#include <unordered_set>
#include <unordered_map>
+#include <boost/thread/mutex.hpp>
#include <boost/serialization/version.hpp>
#include "cryptonote_basic/blobdatatype.h"
#include "cryptonote_basic/cryptonote_basic.h"
@@ -139,6 +140,7 @@ namespace cryptonote
uint64_t m_nonces_stale;
uint64_t m_nonces_bad;
uint64_t m_nonces_dupe;
+ mutable boost::mutex mutex;
};
}
diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp
index 91e4751d1..0d595539d 100644
--- a/src/rpc/zmq_server.cpp
+++ b/src/rpc/zmq_server.cpp
@@ -28,7 +28,6 @@
#include "zmq_server.h"
-#include <boost/utility/string_ref.hpp>
#include <chrono>
#include <cstdint>
#include <system_error>
diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp
index f20fd181a..5c042aa7b 100644
--- a/src/serialization/json_object.cpp
+++ b/src/serialization/json_object.cpp
@@ -120,18 +120,18 @@ void read_hex(const rapidjson::Value& val, epee::span<std::uint8_t> dest)
throw WRONG_TYPE("string");
}
- if (!epee::from_hex::to_buffer(dest, {val.GetString(), val.Size()}))
+ if (!epee::from_hex::to_buffer(dest, {val.GetString(), val.GetStringLength()}))
{
throw BAD_INPUT();
}
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rapidjson::Value& src)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rapidjson::Value& src)
{
src.Accept(dest);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const boost::string_ref i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const boost::string_ref i)
{
dest.String(i.data(), i.size());
}
@@ -146,7 +146,7 @@ void fromJsonValue(const rapidjson::Value& val, std::string& str)
str = val.GetString();
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, bool i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, bool i)
{
dest.Bool(i);
}
@@ -185,7 +185,7 @@ void fromJsonValue(const rapidjson::Value& val, short& i)
to_int(val, i);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const unsigned int i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned int i)
{
dest.Uint(i);
}
@@ -195,7 +195,7 @@ void fromJsonValue(const rapidjson::Value& val, unsigned int& i)
to_uint(val, i);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const int i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const int i)
{
dest.Int(i);
}
@@ -205,7 +205,7 @@ void fromJsonValue(const rapidjson::Value& val, int& i)
to_int(val, i);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const unsigned long long i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long long i)
{
static_assert(!precision_loss<unsigned long long, std::uint64_t>(), "bad uint64 conversion");
dest.Uint64(i);
@@ -216,7 +216,7 @@ void fromJsonValue(const rapidjson::Value& val, unsigned long long& i)
to_uint64(val, i);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const long long i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long long i)
{
static_assert(!precision_loss<long long, std::int64_t>(), "bad int64 conversion");
dest.Int64(i);
@@ -237,7 +237,7 @@ void fromJsonValue(const rapidjson::Value& val, long& i)
to_int64(val, i);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::transaction& tx)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::transaction& tx)
{
dest.StartObject();
@@ -269,7 +269,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx)
GET_FROM_JSON_OBJECT(val, tx.rct_signatures, ringct);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::block& b)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block& b)
{
dest.StartObject();
@@ -301,14 +301,14 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::block& b)
GET_FROM_JSON_OBJECT(val, b.tx_hashes, tx_hashes);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_v& txin)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_v& txin)
{
dest.StartObject();
struct add_input
{
using result_type = void;
- rapidjson::Writer<rapidjson::StringBuffer>& dest;
+ rapidjson::Writer<epee::byte_stream>& dest;
void operator()(cryptonote::txin_to_key const& input) const
{
@@ -373,7 +373,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_v& txin)
}
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_gen& txin)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_gen& txin)
{
dest.StartObject();
@@ -392,7 +392,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_gen& txin)
GET_FROM_JSON_OBJECT(val, txin.height, height);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_to_script& txin)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_script& txin)
{
dest.StartObject();
@@ -417,7 +417,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_script& txin
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_to_scripthash& txin)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_scripthash& txin)
{
dest.StartObject();
@@ -443,7 +443,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_scripthash&
GET_FROM_JSON_OBJECT(val, txin.sigset, sigset);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_to_key& txin)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_key& txin)
{
dest.StartObject();
@@ -467,7 +467,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_key& txin)
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_to_script& txout)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_script& txout)
{
dest.StartObject();
@@ -489,7 +489,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txo
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_to_scripthash& txout)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_scripthash& txout)
{
dest.StartObject();
@@ -509,7 +509,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_scripthash&
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_to_key& txout)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_key& txout)
{
dest.StartObject();
@@ -528,7 +528,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout)
GET_FROM_JSON_OBJECT(val, txout.key, key);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::tx_out& txout)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_out& txout)
{
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, amount, txout.amount);
@@ -537,7 +537,7 @@ void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const crypton
{
using result_type = void;
- rapidjson::Writer<rapidjson::StringBuffer>& dest;
+ rapidjson::Writer<epee::byte_stream>& dest;
void operator()(cryptonote::txout_to_key const& output) const
{
@@ -596,7 +596,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout)
}
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::connection_info& info)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::connection_info& info)
{
dest.StartObject();
@@ -668,7 +668,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::connection_info& inf
GET_FROM_JSON_OBJECT(val, info.current_upload, current_upload);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::tx_blob_entry& tx)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_blob_entry& tx)
{
dest.StartObject();
@@ -689,7 +689,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_blob_entry& tx)
GET_FROM_JSON_OBJECT(val, tx.prunable_hash, prunable_hash);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::block_complete_entry& blk)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block_complete_entry& blk)
{
dest.StartObject();
@@ -711,7 +711,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::block_complete_entry
GET_FROM_JSON_OBJECT(val, blk.txs, transactions);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::block_with_transactions& blk)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::block_with_transactions& blk)
{
dest.StartObject();
@@ -733,7 +733,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::block_with_tran
GET_FROM_JSON_OBJECT(val, blk.transactions, transactions);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::transaction_info& tx_info)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::transaction_info& tx_info)
{
dest.StartObject();
@@ -757,7 +757,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::transaction_inf
GET_FROM_JSON_OBJECT(val, tx_info.transaction, transaction);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_key_and_amount_index& out)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_and_amount_index& out)
{
dest.StartObject();
@@ -779,7 +779,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_and_
GET_FROM_JSON_OBJECT(val, out.key, key);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::amount_with_random_outputs& out)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::amount_with_random_outputs& out)
{
dest.StartObject();
@@ -801,7 +801,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::amount_with_ran
GET_FROM_JSON_OBJECT(val, out.outputs, outputs);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::peer& peer)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::peer& peer)
{
dest.StartObject();
@@ -833,7 +833,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::peer& peer)
GET_FROM_JSON_OBJECT(val, peer.pruning_seed, pruning_seed);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::tx_in_pool& tx)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::tx_in_pool& tx)
{
dest.StartObject();
@@ -880,7 +880,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::tx_in_pool& tx)
GET_FROM_JSON_OBJECT(val, tx.double_spend_seen, double_spend_seen);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::hard_fork_info& info)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::hard_fork_info& info)
{
dest.StartObject();
@@ -914,7 +914,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::hard_fork_info&
GET_FROM_JSON_OBJECT(val, info.earliest_height, earliest_height);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_amount_count& out)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_count& out)
{
dest.StartObject();
@@ -940,7 +940,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_c
GET_FROM_JSON_OBJECT(val, out.recent_count, recent_count);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_amount_and_index& out)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_and_index& out)
{
dest.StartObject();
@@ -962,7 +962,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_a
GET_FROM_JSON_OBJECT(val, out.index, index);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_key_mask_unlocked& out)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_mask_unlocked& out)
{
dest.StartObject();
@@ -985,7 +985,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_mask
GET_FROM_JSON_OBJECT(val, out.unlocked, unlocked);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::error& err)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::error& err)
{
dest.StartObject();
@@ -1008,7 +1008,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error)
GET_FROM_JSON_OBJECT(val, error.message, message);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::BlockHeaderResponse& response)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response)
{
dest.StartObject();
@@ -1045,7 +1045,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResp
GET_FROM_JSON_OBJECT(val, response.reward, reward);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::rctSig& sig)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig)
{
using boost::adaptors::transform;
@@ -1115,7 +1115,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig)
}
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::ecdhTuple& tuple)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::ecdhTuple& tuple)
{
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, mask, tuple.mask);
@@ -1134,7 +1134,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::ecdhTuple& tuple)
GET_FROM_JSON_OBJECT(val, tuple.amount, amount);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::rangeSig& sig)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rangeSig& sig)
{
dest.StartObject();
@@ -1171,7 +1171,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rangeSig& sig)
}
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::Bulletproof& p)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::Bulletproof& p)
{
dest.StartObject();
@@ -1212,7 +1212,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::Bulletproof& p)
GET_FROM_JSON_OBJECT(val, p.t, t);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::boroSig& sig)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::boroSig& sig)
{
dest.StartObject();
@@ -1257,7 +1257,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::boroSig& sig)
GET_FROM_JSON_OBJECT(val, sig.ee, ee);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::mgSig& sig)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::mgSig& sig)
{
dest.StartObject();
@@ -1278,7 +1278,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig)
GET_FROM_JSON_OBJECT(val, sig.cc, cc);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::DaemonInfo& info)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::DaemonInfo& info)
{
dest.StartObject();
@@ -1339,7 +1339,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf
GET_FROM_JSON_OBJECT(val, info.start_time, start_time);
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_distribution& dist)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_distribution& dist)
{
dest.StartObject();
diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h
index 664b539b5..2a9b63b08 100644
--- a/src/serialization/json_object.h
+++ b/src/serialization/json_object.h
@@ -31,9 +31,9 @@
#include <boost/utility/string_ref.hpp>
#include <cstring>
#include <rapidjson/document.h>
-#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
+#include "byte_stream.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "rpc/message_data_structs.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
@@ -123,7 +123,7 @@ void read_hex(const rapidjson::Value& val, epee::span<std::uint8_t> dest);
// POD to json key
template <class Type>
-inline typename std::enable_if<is_to_hex<Type>()>::type toJsonKey(rapidjson::Writer<rapidjson::StringBuffer>& dest, const Type& pod)
+inline typename std::enable_if<is_to_hex<Type>()>::type toJsonKey(rapidjson::Writer<epee::byte_stream>& dest, const Type& pod)
{
const auto hex = epee::to_hex::array(pod);
dest.Key(hex.data(), hex.size());
@@ -131,7 +131,7 @@ inline typename std::enable_if<is_to_hex<Type>()>::type toJsonKey(rapidjson::Wri
// POD to json value
template <class Type>
-inline typename std::enable_if<is_to_hex<Type>()>::type toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const Type& pod)
+inline typename std::enable_if<is_to_hex<Type>()>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Type& pod)
{
const auto hex = epee::to_hex::array(pod);
dest.String(hex.data(), hex.size());
@@ -144,16 +144,16 @@ inline typename std::enable_if<is_to_hex<Type>()>::type fromJsonValue(const rapi
json::read_hex(val, epee::as_mut_byte_span(t));
}
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rapidjson::Value& src);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rapidjson::Value& src);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, boost::string_ref i);
-inline void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const std::string& i)
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, boost::string_ref i);
+inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::string& i)
{
toJsonValue(dest, boost::string_ref{i});
}
void fromJsonValue(const rapidjson::Value& val, std::string& str);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, bool i);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, bool i);
void fromJsonValue(const rapidjson::Value& val, bool& b);
// integers overloads for toJsonValue are not needed for standard promotions
@@ -168,144 +168,144 @@ void fromJsonValue(const rapidjson::Value& val, unsigned short& i);
void fromJsonValue(const rapidjson::Value& val, short& i);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const unsigned i);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned i);
void fromJsonValue(const rapidjson::Value& val, unsigned& i);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const int);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const int);
void fromJsonValue(const rapidjson::Value& val, int& i);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const unsigned long long i);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long long i);
void fromJsonValue(const rapidjson::Value& val, unsigned long long& i);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const long long i);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long long i);
void fromJsonValue(const rapidjson::Value& val, long long& i);
-inline void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const unsigned long i) {
+inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const unsigned long i) {
toJsonValue(dest, static_cast<unsigned long long>(i));
}
void fromJsonValue(const rapidjson::Value& val, unsigned long& i);
-inline void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const long i) {
+inline void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const long i) {
toJsonValue(dest, static_cast<long long>(i));
}
void fromJsonValue(const rapidjson::Value& val, long& i);
// end integers
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::transaction& tx);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::transaction& tx);
void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::block& b);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block& b);
void fromJsonValue(const rapidjson::Value& val, cryptonote::block& b);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_v& txin);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_v& txin);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_v& txin);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_gen& txin);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_gen& txin);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_gen& txin);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_to_script& txin);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_script& txin);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_script& txin);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_to_scripthash& txin);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_scripthash& txin);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_scripthash& txin);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txin_to_key& txin);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txin_to_key& txin);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_key& txin);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_target_v& txout);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_target_v& txout);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_target_v& txout);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_to_script& txout);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_script& txout);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txout);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_to_scripthash& txout);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_scripthash& txout);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_scripthash& txout);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::txout_to_key& txout);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::txout_to_key& txout);
void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::tx_out& txout);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_out& txout);
void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::connection_info& info);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::connection_info& info);
void fromJsonValue(const rapidjson::Value& val, cryptonote::connection_info& info);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::tx_blob_entry& tx);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::tx_blob_entry& tx);
void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_blob_entry& tx);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::block_complete_entry& blk);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::block_complete_entry& blk);
void fromJsonValue(const rapidjson::Value& val, cryptonote::block_complete_entry& blk);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::block_with_transactions& blk);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::block_with_transactions& blk);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::block_with_transactions& blk);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::transaction_info& tx_info);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::transaction_info& tx_info);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::transaction_info& tx_info);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_key_and_amount_index& out);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_and_amount_index& out);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_and_amount_index& out);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::amount_with_random_outputs& out);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::amount_with_random_outputs& out);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::amount_with_random_outputs& out);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::peer& peer);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::peer& peer);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::peer& peer);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::tx_in_pool& tx);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::tx_in_pool& tx);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::tx_in_pool& tx);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::hard_fork_info& info);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::hard_fork_info& info);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::hard_fork_info& info);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_amount_count& out);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_count& out);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_count& out);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_amount_and_index& out);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_amount_and_index& out);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_amount_and_index& out);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_key_mask_unlocked& out);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_key_mask_unlocked& out);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_key_mask_unlocked& out);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::error& err);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::error& err);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::BlockHeaderResponse& response);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResponse& response);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::rctSig& i);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& i);
void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::ecdhTuple& tuple);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::ecdhTuple& tuple);
void fromJsonValue(const rapidjson::Value& val, rct::ecdhTuple& tuple);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::rangeSig& sig);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rangeSig& sig);
void fromJsonValue(const rapidjson::Value& val, rct::rangeSig& sig);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::Bulletproof& p);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::Bulletproof& p);
void fromJsonValue(const rapidjson::Value& val, rct::Bulletproof& p);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::boroSig& sig);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::boroSig& sig);
void fromJsonValue(const rapidjson::Value& val, rct::boroSig& sig);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const rct::mgSig& sig);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::mgSig& sig);
void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::DaemonInfo& info);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::DaemonInfo& info);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& info);
-void toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const cryptonote::rpc::output_distribution& dist);
+void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_distribution& dist);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_distribution& dist);
template <typename Map>
-typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const Map& map);
+typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Map& map);
template <typename Map>
typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type fromJsonValue(const rapidjson::Value& val, Map& map);
template <typename Vec>
-typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const Vec &vec);
+typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec);
template <typename Vec>
typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJsonValue(const rapidjson::Value& val, Vec& vec);
@@ -315,7 +315,7 @@ typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type fromJson
// unfortunately because of how templates work they have to be here.
template <typename Map>
-inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const Map& map)
+inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Map& map)
{
using key_type = typename Map::key_type;
static_assert(std::is_same<std::string, key_type>() || is_to_hex<key_type>(), "invalid map key type");
@@ -351,7 +351,7 @@ inline typename std::enable_if<sfinae::is_map_like<Map>::value, void>::type from
}
template <typename Vec>
-inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<rapidjson::StringBuffer>& dest, const Vec &vec)
+inline typename std::enable_if<sfinae::is_vector_like<Vec>::value, void>::type toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const Vec &vec)
{
dest.StartArray();
for (const auto& t : vec)
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 6cab628e6..3174486a6 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -33,6 +33,11 @@
*
* \brief Source file that defines simple_wallet class.
*/
+
+// use boost bind placeholders for now
+#define BOOST_BIND_GLOBAL_PLACEHOLDERS 1
+#include <boost/bind.hpp>
+
#include <locale.h>
#include <thread>
#include <iostream>
@@ -145,6 +150,7 @@ enum TransferType {
};
static std::string get_human_readable_timespan(std::chrono::seconds seconds);
+static std::string get_human_readable_timespan(uint64_t seconds);
namespace
{
@@ -251,6 +257,7 @@ namespace
const char* USAGE_MMS_SET("mms set <option_name> [<option_value>]");
const char* USAGE_MMS_SEND_SIGNER_CONFIG("mms send_signer_config");
const char* USAGE_MMS_START_AUTO_CONFIG("mms start_auto_config [<label> <label> ...]");
+ const char* USAGE_MMS_CONFIG_CHECKSUM("mms config_checksum");
const char* USAGE_MMS_STOP_AUTO_CONFIG("mms stop_auto_config");
const char* USAGE_MMS_AUTO_CONFIG("mms auto_config <auto_config_token>");
const char* USAGE_PRINT_RING("print_ring <key_image> | <txid>");
@@ -3518,7 +3525,7 @@ simple_wallet::simple_wallet()
tr("Interface with the MMS (Multisig Messaging System)\n"
"<subcommand> is one of:\n"
" init, info, signer, list, next, sync, transfer, delete, send, receive, export, note, show, set, help\n"
- " send_signer_config, start_auto_config, stop_auto_config, auto_config\n"
+ " send_signer_config, start_auto_config, stop_auto_config, auto_config, config_checksum\n"
"Get help about a subcommand with: help_advanced mms <subcommand>"));
m_cmd_binder.set_handler("mms init",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1),
@@ -3587,6 +3594,10 @@ simple_wallet::simple_wallet()
boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1),
tr(USAGE_MMS_START_AUTO_CONFIG),
tr("Start auto-config at the auto-config manager's wallet by issuing auto-config tokens and optionally set others' labels"));
+ m_cmd_binder.set_handler("mms config_checksum",
+ boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1),
+ tr(USAGE_MMS_CONFIG_CHECKSUM),
+ tr("Get a checksum that allows signers to easily check for identical MMS configuration"));
m_cmd_binder.set_handler("mms stop_auto_config",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1),
tr(USAGE_MMS_STOP_AUTO_CONFIG),
@@ -5528,7 +5539,7 @@ void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block
m_refresh_progress_reporter.update(height, false);
}
//----------------------------------------------------------------------------------------------------
-void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time)
+void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time)
{
if (m_locked)
return;
@@ -5539,7 +5550,7 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid,
tr("idx ") << subaddr_index;
const uint64_t warn_height = m_wallet->nettype() == TESTNET ? 1000000 : m_wallet->nettype() == STAGENET ? 50000 : 1650000;
- if (height >= warn_height)
+ if (height >= warn_height && !is_change)
{
std::vector<tx_extra_field> tx_extra_fields;
parse_tx_extra(tx.extra, tx_extra_fields); // failure ok
@@ -5820,15 +5831,19 @@ bool simple_wallet::show_balance_unlocked(bool detailed)
success_msg_writer() << tr("Currently selected account: [") << m_current_subaddress_account << tr("] ") << m_wallet->get_subaddress_label({m_current_subaddress_account, 0});
const std::string tag = m_wallet->get_account_tags().second[m_current_subaddress_account];
success_msg_writer() << tr("Tag: ") << (tag.empty() ? std::string{tr("(No tag assigned)")} : tag);
- uint64_t blocks_to_unlock;
- uint64_t unlocked_balance = m_wallet->unlocked_balance(m_current_subaddress_account, false, &blocks_to_unlock);
+ uint64_t blocks_to_unlock, time_to_unlock;
+ uint64_t unlocked_balance = m_wallet->unlocked_balance(m_current_subaddress_account, false, &blocks_to_unlock, &time_to_unlock);
std::string unlock_time_message;
- if (blocks_to_unlock > 0)
+ if (blocks_to_unlock > 0 && time_to_unlock > 0)
+ unlock_time_message = (boost::format(" (%lu block(s) and %s to unlock)") % blocks_to_unlock % get_human_readable_timespan(time_to_unlock)).str();
+ else if (blocks_to_unlock > 0)
unlock_time_message = (boost::format(" (%lu block(s) to unlock)") % blocks_to_unlock).str();
+ else if (time_to_unlock > 0)
+ unlock_time_message = (boost::format(" (%s to unlock)") % get_human_readable_timespan(time_to_unlock)).str();
success_msg_writer() << tr("Balance: ") << print_money(m_wallet->balance(m_current_subaddress_account, false)) << ", "
<< tr("unlocked balance: ") << print_money(unlocked_balance) << unlock_time_message << extra;
std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account, false);
- std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account, false);
+ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account, false);
if (!detailed || balance_per_subaddress.empty())
return true;
success_msg_writer() << tr("Balance per address:");
@@ -8330,6 +8345,11 @@ static std::string get_human_readable_timespan(std::chrono::seconds seconds)
return sw::tr("a long time");
}
//----------------------------------------------------------------------------------------------------
+static std::string get_human_readable_timespan(uint64_t seconds)
+{
+ return get_human_readable_timespan(std::chrono::seconds(seconds));
+}
+//----------------------------------------------------------------------------------------------------
// mutates local_args as it parses and consumes arguments
bool simple_wallet::get_transfers(std::vector<std::string>& local_args, std::vector<transfer_view>& transfers)
{
@@ -10414,6 +10434,14 @@ bool simple_wallet::user_confirms(const std::string &question)
return !std::cin.eof() && command_line::is_yes(answer);
}
+bool simple_wallet::user_confirms_auto_config()
+{
+ message_writer(console_color_red, true) << tr("WARNING: Using MMS auto-config mechanisms is not trustless");
+ message_writer() << tr("A malicious auto-config manager could send you info about own wallets instead of other signers' info");
+ message_writer() << tr("If in doubt do not use auto-config or at least compare configs using the \"mms config_checksum\" command");
+ return user_confirms("Accept the risks and continue?");
+}
+
bool simple_wallet::get_number_from_arg(const std::string &arg, uint32_t &number, const uint32_t lower_bound, const uint32_t upper_bound)
{
bool valid = false;
@@ -10566,7 +10594,7 @@ void simple_wallet::show_message(const mms::message &m)
case mms::message_type::additional_key_set:
case mms::message_type::note:
display_content = true;
- ms.get_sanitized_message_text(m, sanitized_text);
+ sanitized_text = mms::message_store::get_sanitized_text(m.content, 1000);
break;
default:
display_content = false;
@@ -10915,6 +10943,11 @@ void simple_wallet::mms_next(const std::vector<std::string> &args)
{
break;
}
+ if (!user_confirms_auto_config())
+ {
+ message_writer() << tr("You can use the \"mms delete\" command to delete any unwanted message");
+ break;
+ }
}
ms.process_signer_config(state, m.content);
ms.stop_auto_config();
@@ -11241,6 +11274,18 @@ void simple_wallet::mms_start_auto_config(const std::vector<std::string> &args)
list_signers(ms.get_all_signers());
}
+void simple_wallet::mms_config_checksum(const std::vector<std::string> &args)
+{
+ if (args.size() != 0)
+ {
+ fail_msg_writer() << tr("Usage: mms config_checksum");
+ return;
+ }
+ mms::message_store& ms = m_wallet->get_message_store();
+ LOCK_IDLE_SCOPE();
+ message_writer() << ms.get_config_checksum();
+}
+
void simple_wallet::mms_stop_auto_config(const std::vector<std::string> &args)
{
if (args.size() != 0)
@@ -11271,6 +11316,10 @@ void simple_wallet::mms_auto_config(const std::vector<std::string> &args)
fail_msg_writer() << tr("Invalid auto-config token");
return;
}
+ if (!user_confirms_auto_config())
+ {
+ return;
+ }
mms::authorized_signer me = ms.get_signer(0);
if (me.auto_config_running)
{
@@ -11383,6 +11432,10 @@ bool simple_wallet::mms(const std::vector<std::string> &args)
{
mms_start_auto_config(mms_args);
}
+ else if (sub_command == "config_checksum")
+ {
+ mms_config_checksum(mms_args);
+ }
else if (sub_command == "stop_auto_config")
{
mms_stop_auto_config(mms_args);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index ec2e86250..2ff434c23 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -53,7 +53,7 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.simplewallet"
// Hardcode Monero's donation address (see #1447)
-constexpr const char MONERO_DONATION_ADDR[] = "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A";
+constexpr const char MONERO_DONATION_ADDR[] = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
/*!
* \namespace cryptonote
@@ -343,7 +343,7 @@ namespace cryptonote
//----------------- i_wallet2_callback ---------------------
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
- virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time);
+ virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time);
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index);
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index);
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx);
@@ -479,6 +479,7 @@ namespace cryptonote
void ask_send_all_ready_messages();
void check_for_messages();
bool user_confirms(const std::string &question);
+ bool user_confirms_auto_config();
bool get_message_from_arg(const std::string &arg, mms::message &m);
bool get_number_from_arg(const std::string &arg, uint32_t &number, const uint32_t lower_bound, const uint32_t upper_bound);
@@ -499,6 +500,7 @@ namespace cryptonote
void mms_help(const std::vector<std::string> &args);
void mms_send_signer_config(const std::vector<std::string> &args);
void mms_start_auto_config(const std::vector<std::string> &args);
+ void mms_config_checksum(const std::vector<std::string> &args);
void mms_stop_auto_config(const std::vector<std::string> &args);
void mms_auto_config(const std::vector<std::string> &args);
};
diff --git a/src/version.cpp.in b/src/version.cpp.in
index ccb88f1fe..2071acb8c 100644
--- a/src/version.cpp.in
+++ b/src/version.cpp.in
@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
-#define DEF_MONERO_VERSION "0.15.0.0"
+#define DEF_MONERO_VERSION "0.16.0.0"
#define DEF_MONERO_RELEASE_NAME "Carbon Chamaeleon"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index d89261c64..0badd922a 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -157,7 +157,7 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
}
}
- virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time)
+ virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time)
{
std::string tx_hash = epee::string_tools::pod_to_hex(txid);
diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp
index 1bd462ef5..fb07b42f0 100644
--- a/src/wallet/message_store.cpp
+++ b/src/wallet/message_store.cpp
@@ -39,6 +39,7 @@
#include "serialization/binary_utils.h"
#include "common/base58.h"
#include "common/util.h"
+#include "common/utf8.h"
#include "string_tools.h"
@@ -129,18 +130,18 @@ void message_store::set_signer(const multisig_wallet_state &state,
authorized_signer &m = m_signers[index];
if (label)
{
- m.label = label.get();
+ m.label = get_sanitized_text(label.get(), 50);
}
if (transport_address)
{
- m.transport_address = transport_address.get();
+ m.transport_address = get_sanitized_text(transport_address.get(), 200);
}
if (monero_address)
{
m.monero_address_known = true;
m.monero_address = monero_address.get();
}
- // Save to minimize the chance to loose that info (at least while in beta)
+ // Save to minimize the chance to loose that info
save(state);
}
@@ -202,6 +203,13 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con
}
uint32_t num_signers = (uint32_t)signers.size();
THROW_WALLET_EXCEPTION_IF(num_signers != m_num_authorized_signers, tools::error::wallet_internal_error, "Wrong number of signers in config: " + std::to_string(num_signers));
+ for (uint32_t i = 0; i < num_signers; ++i)
+ {
+ authorized_signer &m = signers[i];
+ m.label = get_sanitized_text(m.label, 50);
+ m.transport_address = get_sanitized_text(m.transport_address, 200);
+ m.auto_config_token = get_sanitized_text(m.auto_config_token, 20);
+ }
}
void message_store::process_signer_config(const multisig_wallet_state &state, const std::string &signer_config)
@@ -242,10 +250,10 @@ void message_store::process_signer_config(const multisig_wallet_state &state, co
}
}
authorized_signer &modify = m_signers[take_index];
- modify.label = m.label; // ALWAYS set label, see comments above
+ modify.label = get_sanitized_text(m.label, 50); // ALWAYS set label, see comments above
if (!modify.me)
{
- modify.transport_address = m.transport_address;
+ modify.transport_address = get_sanitized_text(m.transport_address, 200);
modify.monero_address_known = m.monero_address_known;
if (m.monero_address_known)
{
@@ -392,6 +400,45 @@ void message_store::process_auto_config_data_message(uint32_t id)
signer.auto_config_running = false;
}
+void add_hash(crypto::hash &sum, const crypto::hash &summand)
+{
+ for (uint32_t i = 0; i < crypto::HASH_SIZE; ++i)
+ {
+ uint32_t x = (uint32_t)sum.data[i];
+ uint32_t y = (uint32_t)summand.data[i];
+ sum.data[i] = (char)((x + y) % 256);
+ }
+}
+
+// Calculate a checksum that allows signers to make sure they work with an identical signer config
+// by exchanging and comparing checksums out-of-band i.e. not using the MMS;
+// Because different signers have a different order of signers in the config work with "adding"
+// individual hashes because that operation is commutative
+std::string message_store::get_config_checksum() const
+{
+ crypto::hash sum = crypto::null_hash;
+ uint32_t num = SWAP32LE(m_num_authorized_signers);
+ add_hash(sum, crypto::cn_fast_hash(&num, sizeof(num)));
+ num = SWAP32LE(m_num_required_signers);
+ add_hash(sum, crypto::cn_fast_hash(&num, sizeof(num)));
+ for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
+ {
+ const authorized_signer &m = m_signers[i];
+ add_hash(sum, crypto::cn_fast_hash(m.transport_address.data(), m.transport_address.size()));
+ if (m.monero_address_known)
+ {
+ add_hash(sum, crypto::cn_fast_hash(&m.monero_address.m_spend_public_key, sizeof(m.monero_address.m_spend_public_key)));
+ add_hash(sum, crypto::cn_fast_hash(&m.monero_address.m_view_public_key, sizeof(m.monero_address.m_view_public_key)));
+ }
+ }
+ std::string checksum_bytes;
+ checksum_bytes += sum.data[0];
+ checksum_bytes += sum.data[1];
+ checksum_bytes += sum.data[2];
+ checksum_bytes += sum.data[3];
+ return epee::string_tools::buff_to_hex_nodelimer(checksum_bytes);
+}
+
void message_store::stop_auto_config()
{
for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
@@ -661,32 +708,38 @@ void message_store::delete_all_messages()
m_messages.clear();
}
-// Make a message text, which is "attacker controlled data", reasonably safe to display
+// Make a text, which is "attacker controlled data", reasonably safe to display
// This is mostly geared towards the safe display of notes sent by "mms note" with a "mms show" command
-void message_store::get_sanitized_message_text(const message &m, std::string &sanitized_text) const
+std::string message_store::get_sanitized_text(const std::string &text, size_t max_length)
{
- sanitized_text.clear();
-
// Restrict the size to fend of DOS-style attacks with heaps of data
- size_t length = std::min(m.content.length(), (size_t)1000);
+ size_t length = std::min(text.length(), max_length);
+ std::string sanitized_text = text.substr(0, length);
- for (size_t i = 0; i < length; ++i)
+ try
{
- char c = m.content[i];
- if ((int)c < 32)
+ sanitized_text = tools::utf8canonical(sanitized_text, [](wint_t c)
{
- // Strip out any controls, especially ESC for getting rid of potentially dangerous
- // ANSI escape sequences that a console window might interpret
- c = ' ';
- }
- else if ((c == '<') || (c == '>'))
- {
- // Make XML or HTML impossible that e.g. might contain scripts that Qt might execute
- // when displayed in the GUI wallet
- c = ' ';
- }
- sanitized_text += c;
+ if ((c < 0x20) || (c == 0x7f) || (c >= 0x80 && c <= 0x9f))
+ {
+ // Strip out any controls, especially ESC for getting rid of potentially dangerous
+ // ANSI escape sequences that a console window might interpret
+ c = '?';
+ }
+ else if ((c == '<') || (c == '>'))
+ {
+ // Make XML or HTML impossible that e.g. might contain scripts that Qt might execute
+ // when displayed in the GUI wallet
+ c = '?';
+ }
+ return c;
+ });
+ }
+ catch (const std::exception &e)
+ {
+ sanitized_text = "(Illegal UTF-8 string)";
}
+ return sanitized_text;
}
void message_store::write_to_file(const multisig_wallet_state &state, const std::string &filename)
@@ -724,7 +777,7 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std
{
// Simply do nothing if the file is not there; allows e.g. easy recovery
// from problems with the MMS by deleting the file
- MERROR("No message store file found: " << filename);
+ MINFO("No message store file found: " << filename);
return;
}
diff --git a/src/wallet/message_store.h b/src/wallet/message_store.h
index d40daf186..9055fd776 100644
--- a/src/wallet/message_store.h
+++ b/src/wallet/message_store.h
@@ -242,6 +242,7 @@ namespace mms
size_t add_auto_config_data_message(const multisig_wallet_state &state,
const std::string &auto_config_token);
void process_auto_config_data_message(uint32_t id);
+ std::string get_config_checksum() const;
void stop_auto_config();
// Process data just created by "me" i.e. the own local wallet, e.g. as the result of a "prepare_multisig" command
@@ -275,7 +276,7 @@ namespace mms
void set_message_processed_or_sent(uint32_t id);
void delete_message(uint32_t id);
void delete_all_messages();
- void get_sanitized_message_text(const message &m, std::string &sanitized_text) const;
+ static std::string get_sanitized_text(const std::string &text, size_t max_length);
void send_message(const multisig_wallet_state &state, uint32_t id);
bool check_for_messages(const multisig_wallet_state &state, std::vector<message> &messages);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 476248d18..144e7e3f2 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -947,7 +947,7 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra)
static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet)
{
- shim->get_tx_pub_key_from_received_outs = boost::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, _1);
+ shim->get_tx_pub_key_from_received_outs = std::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, std::placeholders::_1);
}
bool get_pruned_tx(const cryptonote::COMMAND_RPC_GET_TRANSACTIONS::entry &entry, cryptonote::transaction &tx, crypto::hash &tx_hash)
@@ -1523,6 +1523,18 @@ void wallet2::add_subaddress(uint32_t index_major, const std::string& label)
m_subaddress_labels[index_major][index_minor] = label;
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::should_expand(const cryptonote::subaddress_index &index) const
+{
+ const uint32_t last_major = m_subaddress_labels.size() - 1 > (std::numeric_limits<uint32_t>::max() - m_subaddress_lookahead_major) ? std::numeric_limits<uint32_t>::max() : (m_subaddress_labels.size() + m_subaddress_lookahead_major - 1);
+ if (index.major > last_major)
+ return false;
+ const size_t nsub = index.major < m_subaddress_labels.size() ? m_subaddress_labels[index.major].size() : 0;
+ const uint32_t last_minor = nsub - 1 > (std::numeric_limits<uint32_t>::max() - m_subaddress_lookahead_minor) ? std::numeric_limits<uint32_t>::max() : (nsub + m_subaddress_lookahead_minor - 1);
+ if (index.minor > last_minor)
+ return false;
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{
hw::device &hwdev = m_account.get_device();
@@ -1855,6 +1867,20 @@ void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::has
}
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::spends_one_of_ours(const cryptonote::transaction &tx) const
+{
+ for (const auto &in: tx.vin)
+ {
+ if (in.type() != typeid(cryptonote::txin_to_key))
+ continue;
+ const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in);
+ auto it = m_key_images.find(in_to_key.k_image);
+ if (it != m_key_images.end())
+ return true;
+ }
+ return false;
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
{
PERF_TIMER(process_new_transaction);
@@ -2108,7 +2134,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_amount = amount;
td.m_pk_index = pk_index - 1;
td.m_subaddr_index = tx_scan_info[o].received->index;
- if (tx_scan_info[o].received->index.major < m_subaddress_labels.size() && tx_scan_info[o].received->index.minor < m_subaddress_labels[tx_scan_info[o].received->index.major].size())
+ if (should_expand(tx_scan_info[o].received->index))
expand_subaddresses(tx_scan_info[o].received->index);
if (tx.vout[o].amount == 0)
{
@@ -2141,7 +2167,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (0 != m_callback)
- m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, td.m_tx.unlock_time);
+ m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time);
}
total_received_1 += amount;
notify = true;
@@ -2187,7 +2213,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_amount = amount;
td.m_pk_index = pk_index - 1;
td.m_subaddr_index = tx_scan_info[o].received->index;
- if (tx_scan_info[o].received->index.major < m_subaddress_labels.size() && tx_scan_info[o].received->index.minor < m_subaddress_labels[tx_scan_info[o].received->index.major].size())
+ if (should_expand(tx_scan_info[o].received->index))
expand_subaddresses(tx_scan_info[o].received->index);
if (tx.vout[o].amount == 0)
{
@@ -2218,7 +2244,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (0 != m_callback)
- m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, td.m_tx.unlock_time);
+ m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time);
}
total_received_1 += extra_amount;
notify = true;
@@ -3978,13 +4004,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
// Load keys from buffer
boost::optional<crypto::chacha_key> keys_to_encrypt;
- try {
- r = wallet2::load_keys_buf(keys_file_buf, password, keys_to_encrypt);
- } catch (const std::exception& e) {
- std::size_t found = string(e.what()).find("failed to deserialize keys buffer");
- THROW_WALLET_EXCEPTION_IF(found != std::string::npos, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"');
- throw e;
- }
+ r = wallet2::load_keys_buf(keys_file_buf, password, keys_to_encrypt);
// Rewrite with encrypted keys if unencrypted, ignore errors
if (r && keys_to_encrypt != boost::none)
@@ -4848,6 +4868,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
std::vector<crypto::secret_key> multisig_keys;
rct::key spend_pkey = rct::identity();
rct::key spend_skey;
+ auto wiper = epee::misc_utils::create_scope_leave_handler([&](){memwipe(&spend_skey, sizeof(spend_skey));});
std::vector<crypto::public_key> multisig_signers;
// decrypt keys
@@ -5493,13 +5514,12 @@ bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout)
cryptonote::COMMAND_RPC_GET_VERSION::request req_t = AUTO_VAL_INIT(req_t);
cryptonote::COMMAND_RPC_GET_VERSION::response resp_t = AUTO_VAL_INIT(resp_t);
bool r = invoke_http_json_rpc("/json_rpc", "get_version", req_t, resp_t);
- if(!r) {
+ if(!r || resp_t.status != CORE_RPC_STATUS_OK) {
if(version)
*version = 0;
return false;
}
- if (resp_t.status == CORE_RPC_STATUS_OK)
- m_rpc_version = resp_t.version;
+ m_rpc_version = resp_t.version;
}
if (version)
*version = m_rpc_version;
@@ -5912,18 +5932,22 @@ uint64_t wallet2::balance(uint32_t index_major, bool strict) const
return amount;
}
//----------------------------------------------------------------------------------------------------
-uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *blocks_to_unlock) const
+uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *blocks_to_unlock, uint64_t *time_to_unlock) const
{
uint64_t amount = 0;
if (blocks_to_unlock)
*blocks_to_unlock = 0;
+ if (time_to_unlock)
+ *time_to_unlock = 0;
if(m_light_wallet)
return m_light_wallet_balance;
for (const auto& i : unlocked_balance_per_subaddress(index_major, strict))
{
amount += i.second.first;
- if (blocks_to_unlock && i.second.second > *blocks_to_unlock)
- *blocks_to_unlock = i.second.second;
+ if (blocks_to_unlock && i.second.second.first > *blocks_to_unlock)
+ *blocks_to_unlock = i.second.second.first;
+ if (time_to_unlock && i.second.second.second > *time_to_unlock)
+ *time_to_unlock = i.second.second.second;
}
return amount;
}
@@ -5960,35 +5984,40 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo
return amount_per_subaddr;
}
//----------------------------------------------------------------------------------------------------
-std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_subaddress(uint32_t index_major, bool strict) const
+std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> wallet2::unlocked_balance_per_subaddress(uint32_t index_major, bool strict) const
{
- std::map<uint32_t, std::pair<uint64_t, uint64_t>> amount_per_subaddr;
+ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> amount_per_subaddr;
const uint64_t blockchain_height = get_blockchain_current_height();
+ const uint64_t now = time(NULL);
for(const transfer_details& td: m_transfers)
{
if(td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen)
{
- uint64_t amount = 0, blocks_to_unlock = 0;
+ uint64_t amount = 0, blocks_to_unlock = 0, time_to_unlock = 0;
if (is_transfer_unlocked(td))
{
amount = td.amount();
blocks_to_unlock = 0;
+ time_to_unlock = 0;
}
else
{
uint64_t unlock_height = td.m_block_height + std::max<uint64_t>(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS);
if (td.m_tx.unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && td.m_tx.unlock_time > unlock_height)
unlock_height = td.m_tx.unlock_time;
+ uint64_t unlock_time = td.m_tx.unlock_time >= CRYPTONOTE_MAX_BLOCK_NUMBER ? td.m_tx.unlock_time : 0;
blocks_to_unlock = unlock_height > blockchain_height ? unlock_height - blockchain_height : 0;
+ time_to_unlock = unlock_time > now ? unlock_time - now : 0;
amount = 0;
}
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
if (found == amount_per_subaddr.end())
- amount_per_subaddr[td.m_subaddr_index.minor] = std::make_pair(amount, blocks_to_unlock);
+ amount_per_subaddr[td.m_subaddr_index.minor] = std::make_pair(amount, std::make_pair(blocks_to_unlock, time_to_unlock));
else
{
found->second.first += amount;
- found->second.second = std::max(found->second.second, blocks_to_unlock);
+ found->second.second.first = std::max(found->second.second.first, blocks_to_unlock);
+ found->second.second.second = std::max(found->second.second.second, time_to_unlock);
}
}
}
@@ -6003,17 +6032,21 @@ uint64_t wallet2::balance_all(bool strict) const
return r;
}
//----------------------------------------------------------------------------------------------------
-uint64_t wallet2::unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock) const
+uint64_t wallet2::unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock, uint64_t *time_to_unlock) const
{
uint64_t r = 0;
if (blocks_to_unlock)
*blocks_to_unlock = 0;
+ if (time_to_unlock)
+ *time_to_unlock = 0;
for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major)
{
- uint64_t local_blocks_to_unlock;
- r += unlocked_balance(index_major, strict, blocks_to_unlock ? &local_blocks_to_unlock : NULL);
+ uint64_t local_blocks_to_unlock, local_time_to_unlock;
+ r += unlocked_balance(index_major, strict, blocks_to_unlock ? &local_blocks_to_unlock : NULL, time_to_unlock ? &local_time_to_unlock : NULL);
if (blocks_to_unlock)
*blocks_to_unlock = std::max(*blocks_to_unlock, local_blocks_to_unlock);
+ if (time_to_unlock)
+ *time_to_unlock = std::max(*time_to_unlock, local_time_to_unlock);
}
return r;
}
@@ -6492,7 +6525,7 @@ void wallet2::commit_tx(pending_tx& ptx)
// tx generated, get rid of used k values
for (size_t idx: ptx.selected_transfers)
- m_transfers[idx].m_multisig_k.clear();
+ memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
//fee includes dust if dust policy specified it.
LOG_PRINT_L1("Transaction successfully sent. <" << txid << ">" << ENDL
@@ -6934,13 +6967,13 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs)
// txes generated, get rid of used k values
for (size_t n = 0; n < txs.m_ptx.size(); ++n)
for (size_t idx: txs.m_ptx[n].construction_data.selected_transfers)
- m_transfers[idx].m_multisig_k.clear();
+ memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
// zero out some data we don't want to share
for (auto &ptx: txs.m_ptx)
{
for (auto &e: ptx.construction_data.sources)
- e.multisig_kLRki.k = rct::zero();
+ memwipe(&e.multisig_kLRki.k, sizeof(e.multisig_kLRki.k));
}
for (auto &ptx: txs.m_ptx)
@@ -7148,10 +7181,12 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
ptx.tx.rct_signatures = sig.sigs;
rct::keyV k;
+ rct::key skey = rct::zero();
+ auto wiper = epee::misc_utils::create_scope_leave_handler([&](){ memwipe(k.data(), k.size() * sizeof(k[0])); memwipe(&skey, sizeof(skey)); });
+
for (size_t idx: sd.selected_transfers)
k.push_back(get_multisig_k(idx, sig.used_L));
- rct::key skey = rct::zero();
for (const auto &msk: get_account().get_multisig_keys())
{
crypto::public_key pmsk = get_multisig_signing_public_key(msk);
@@ -7199,7 +7234,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
// txes generated, get rid of used k values
for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n)
for (size_t idx: exported_txs.m_ptx[n].construction_data.selected_transfers)
- m_transfers[idx].m_multisig_k.clear();
+ memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
exported_txs.m_signers.insert(get_multisig_signer_public_key());
@@ -8997,7 +9032,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
continue;
}
- if (!is_spent(td2, false) && !td2.m_frozen && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
+ if (!is_spent(td2, false) && !td2.m_frozen && !td2.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
{
// update our picks if those outputs are less related than any we
// already found. If the same, don't update, and oldest suitable outputs
@@ -9652,7 +9687,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// throw if attempting a transaction with no money
THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination);
- std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account, false);
+ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account, false);
std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account, false);
if (subaddr_indices.empty()) // "index=<N1>[,<N2>,...]" wasn't specified -> use all the indices with non-zero unlocked balance
@@ -12757,7 +12792,7 @@ process:
const crypto::public_key& out_key = boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key;
bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
- if (td.m_subaddr_index.major < m_subaddress_labels.size() && td.m_subaddr_index.minor < m_subaddress_labels[td.m_subaddr_index.major].size())
+ if (should_expand(td.m_subaddr_index))
expand_subaddresses(td.m_subaddr_index);
td.m_key_image_known = true;
td.m_key_image_request = true;
@@ -12950,7 +12985,7 @@ cryptonote::blobdata wallet2::export_multisig()
{
transfer_details &td = m_transfers[n];
crypto::key_image ki;
- td.m_multisig_k.clear();
+ memwipe(td.m_multisig_k.data(), td.m_multisig_k.size() * sizeof(td.m_multisig_k[0]));
info[n].m_LR.clear();
info[n].m_partial_key_images.clear();
@@ -13059,6 +13094,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
CHECK_AND_ASSERT_THROW_MES(info.size() + 1 <= m_multisig_signers.size() && info.size() + 1 >= m_multisig_threshold, "Wrong number of multisig sources");
std::vector<std::vector<rct::key>> k;
+ auto wiper = epee::misc_utils::create_scope_leave_handler([&](){for (auto &v: k) memwipe(v.data(), v.size() * sizeof(v[0]));});
k.reserve(m_transfers.size());
for (const auto &td: m_transfers)
k.push_back(td.m_multisig_k);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 7618e310c..3a14215b3 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -131,7 +131,7 @@ private:
public:
// Full wallet callbacks
virtual void on_new_block(uint64_t height, const cryptonote::block& block) {}
- virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time) {}
+ virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) {}
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index) {}
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index) {}
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) {}
@@ -835,13 +835,13 @@ private:
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major, bool strict) const;
- uint64_t unlocked_balance(uint32_t subaddr_index_major, bool strict, uint64_t *blocks_to_unlock = NULL) const;
+ uint64_t unlocked_balance(uint32_t subaddr_index_major, bool strict, uint64_t *blocks_to_unlock = NULL, uint64_t *time_to_unlock = NULL) const;
// locked & unlocked balance per subaddress of given or current subaddress account
std::map<uint32_t, uint64_t> balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const;
- std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const;
+ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const;
// all locked & unlocked balances of all subaddress accounts
uint64_t balance_all(bool strict) const;
- uint64_t unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock = NULL) const;
+ uint64_t unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock = NULL, uint64_t *time_to_unlock = NULL) const;
template<typename T>
void transfer_selected(const std::vector<cryptonote::tx_destination_entry>& dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
@@ -1516,6 +1516,9 @@ private:
std::string get_client_signature() const;
void check_rpc_cost(const char *call, uint64_t post_call_credits, uint64_t pre_credits, double expected_cost);
+ bool should_expand(const cryptonote::subaddress_index &index) const;
+ bool spends_one_of_ours(const cryptonote::transaction &tx) const;
+
cryptonote::account_base m_account;
boost::optional<epee::net_utils::http::login> m_daemon_login;
std::string m_daemon_address;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index db2e2344b..30eed07e7 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -428,10 +428,10 @@ namespace tools
try
{
res.balance = req.all_accounts ? m_wallet->balance_all(req.strict) : m_wallet->balance(req.account_index, req.strict);
- res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all(req.strict, &res.blocks_to_unlock) : m_wallet->unlocked_balance(req.account_index, req.strict, &res.blocks_to_unlock);
+ res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all(req.strict, &res.blocks_to_unlock, &res.time_to_unlock) : m_wallet->unlocked_balance(req.account_index, req.strict, &res.blocks_to_unlock, &res.time_to_unlock);
res.multisig_import_needed = m_wallet->multisig() && m_wallet->has_multisig_partial_key_images();
std::map<uint32_t, std::map<uint32_t, uint64_t>> balance_per_subaddress_per_account;
- std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress_per_account;
+ std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>>> unlocked_balance_per_subaddress_per_account;
if (req.all_accounts)
{
for (uint32_t account_index = 0; account_index < m_wallet->get_num_subaddress_accounts(); ++account_index)
@@ -451,7 +451,7 @@ namespace tools
{
uint32_t account_index = p.first;
std::map<uint32_t, uint64_t> balance_per_subaddress = p.second;
- std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress = unlocked_balance_per_subaddress_per_account[account_index];
+ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress = unlocked_balance_per_subaddress_per_account[account_index];
std::set<uint32_t> address_indices;
if (!req.all_accounts && !req.address_indices.empty())
{
@@ -471,7 +471,8 @@ namespace tools
info.address = m_wallet->get_subaddress_as_str(index);
info.balance = balance_per_subaddress[i];
info.unlocked_balance = unlocked_balance_per_subaddress[i].first;
- info.blocks_to_unlock = unlocked_balance_per_subaddress[i].second;
+ info.blocks_to_unlock = unlocked_balance_per_subaddress[i].second.first;
+ info.time_to_unlock = unlocked_balance_per_subaddress[i].second.second;
info.label = m_wallet->get_subaddress_label(index);
info.num_unspent_outputs = std::count_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == index; });
res.per_subaddress.emplace_back(std::move(info));
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index a212b79e6..507ff4f6c 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -47,7 +47,7 @@
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define WALLET_RPC_VERSION_MAJOR 1
-#define WALLET_RPC_VERSION_MINOR 17
+#define WALLET_RPC_VERSION_MINOR 18
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
namespace tools
@@ -84,6 +84,7 @@ namespace wallet_rpc
std::string label;
uint64_t num_unspent_outputs;
uint64_t blocks_to_unlock;
+ uint64_t time_to_unlock;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(account_index)
@@ -94,6 +95,7 @@ namespace wallet_rpc
KV_SERIALIZE(label)
KV_SERIALIZE(num_unspent_outputs)
KV_SERIALIZE(blocks_to_unlock)
+ KV_SERIALIZE(time_to_unlock)
END_KV_SERIALIZE_MAP()
};
@@ -104,6 +106,7 @@ namespace wallet_rpc
bool multisig_import_needed;
std::vector<per_subaddress_info> per_subaddress;
uint64_t blocks_to_unlock;
+ uint64_t time_to_unlock;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(balance)
@@ -111,6 +114,7 @@ namespace wallet_rpc
KV_SERIALIZE(multisig_import_needed)
KV_SERIALIZE(per_subaddress)
KV_SERIALIZE(blocks_to_unlock)
+ KV_SERIALIZE(time_to_unlock)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;