aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt25
-rw-r--r--src/blockchain_db/blockchain_db.cpp11
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp3
-rw-r--r--src/blockchain_utilities/blockchain-stats-readme.md54
-rw-r--r--src/blockchain_utilities/blockchain_blackball.cpp4
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp16
-rw-r--r--src/blocks/CMakeLists.txt30
-rw-r--r--src/cryptonote_basic/CMakeLists.txt9
-rw-r--r--src/cryptonote_basic/cryptonote_basic.h20
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp76
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h4
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils_basic.cpp49
-rw-r--r--src/cryptonote_basic/tx_extra.h9
-rw-r--r--src/cryptonote_core/blockchain.cpp17
-rw-r--r--src/cryptonote_core/blockchain.h2
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp10
-rw-r--r--src/cryptonote_core/cryptonote_core.h4
-rw-r--r--src/device/CMakeLists.txt1
-rw-r--r--src/device/device_ledger.cpp14
-rw-r--r--src/device/device_ledger.hpp5
-rw-r--r--src/device_trezor/trezor/protocol.hpp4
-rw-r--r--src/device_trezor/trezor/transport.cpp13
-rw-r--r--src/p2p/net_node.inl4
-rw-r--r--src/ringct/rctTypes.h8
-rw-r--r--src/rpc/core_rpc_server.cpp2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h4
-rw-r--r--src/rpc/rpc_payment.cpp5
-rw-r--r--src/serialization/binary_archive.h90
-rw-r--r--src/serialization/binary_utils.h3
-rw-r--r--src/serialization/container.h10
-rw-r--r--src/serialization/crypto.h6
-rw-r--r--src/serialization/debug_archive.h1
-rw-r--r--src/serialization/difficulty_type.h8
-rw-r--r--src/serialization/json_archive.h7
-rw-r--r--src/serialization/pair.h12
-rw-r--r--src/serialization/serialization.h36
-rw-r--r--src/serialization/string.h2
-rw-r--r--src/serialization/variant.h8
-rw-r--r--src/simplewallet/simplewallet.cpp4
-rw-r--r--src/wallet/api/CMakeLists.txt3
-rw-r--r--src/wallet/api/address_book.cpp4
-rw-r--r--src/wallet/api/address_book.h3
-rw-r--r--src/wallet/api/pending_transaction.cpp3
-rw-r--r--src/wallet/api/pending_transaction.h2
-rw-r--r--src/wallet/api/transaction_history.cpp2
-rw-r--r--src/wallet/api/transaction_history.h3
-rw-r--r--src/wallet/api/transaction_info.cpp2
-rw-r--r--src/wallet/api/transaction_info.h2
-rw-r--r--src/wallet/api/unsigned_transaction.cpp3
-rw-r--r--src/wallet/api/unsigned_transaction.h2
-rw-r--r--src/wallet/api/utils.cpp2
-rw-r--r--src/wallet/api/wallet.cpp67
-rw-r--r--src/wallet/api/wallet.h9
-rw-r--r--src/wallet/api/wallet2_api.h15
-rw-r--r--src/wallet/api/wallet_manager.cpp2
-rw-r--r--src/wallet/api/wallet_manager.h2
-rw-r--r--src/wallet/message_store.cpp16
-rw-r--r--src/wallet/wallet2.cpp48
-rw-r--r--src/wallet/wallet_rpc_server.cpp112
-rw-r--r--src/wallet/wallet_rpc_server.h10
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h84
61 files changed, 631 insertions, 355 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9904c5de7..aaaae3a09 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -77,30 +77,7 @@ function (monero_add_executable name)
enable_stack_trace("${name}")
monero_set_target_no_relink("${name}")
-endfunction ()
-
-function (monero_add_library name)
- monero_add_library_with_deps(NAME "${name}" SOURCES ${ARGN})
-endfunction()
-
-function (monero_add_library_with_deps)
- cmake_parse_arguments(MONERO_ADD_LIBRARY "" "NAME" "DEPENDS;SOURCES" ${ARGN})
- source_group("${MONERO_ADD_LIBRARY_NAME}" FILES ${MONERO_ADD_LIBRARY_SOURCES})
-
- # Define a ("virtual") object library and an actual library that links those
- # objects together. The virtual libraries can be arbitrarily combined to link
- # any subset of objects into one library archive. This is used for releasing
- # libwallet, which combines multiple components.
- set(objlib obj_${MONERO_ADD_LIBRARY_NAME})
- add_library(${objlib} OBJECT ${MONERO_ADD_LIBRARY_SOURCES})
- add_library("${MONERO_ADD_LIBRARY_NAME}" $<TARGET_OBJECTS:${objlib}>)
- monero_set_target_no_relink("${MONERO_ADD_LIBRARY_NAME}")
- if (MONERO_ADD_LIBRARY_DEPENDS)
- add_dependencies(${objlib} ${MONERO_ADD_LIBRARY_DEPENDS})
- endif()
- set_property(TARGET "${MONERO_ADD_LIBRARY_NAME}" PROPERTY FOLDER "libs")
- target_compile_definitions(${objlib}
- PRIVATE $<TARGET_PROPERTY:${MONERO_ADD_LIBRARY_NAME},INTERFACE_COMPILE_DEFINITIONS>)
+ monero_set_target_strip ("${name}")
endfunction ()
include(Version)
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index 5e12fa8ec..a84a4148d 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -216,15 +216,8 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
}
else
{
- LOG_PRINT_L1("Unsupported input type, removing key images and aborting transaction addition");
- for (const txin_v& tx_input : tx.vin)
- {
- if (tx_input.type() == typeid(txin_to_key))
- {
- remove_spent_key(boost::get<txin_to_key>(tx_input).k_image);
- }
- }
- return;
+ LOG_PRINT_L1("Unsupported input type, aborting transaction addition");
+ throw std::runtime_error("Unexpected input type, aborting");
}
}
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 5f3b495b0..1d7b10648 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -1354,7 +1354,8 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
m_folder = filename;
- check_mmap_support();
+ try { check_mmap_support(); }
+ catch(...) { MERROR("Failed to check for mmap support, proceeding"); }
#ifdef __OpenBSD__
if ((mdb_flags & MDB_WRITEMAP) == 0) {
diff --git a/src/blockchain_utilities/blockchain-stats-readme.md b/src/blockchain_utilities/blockchain-stats-readme.md
new file mode 100644
index 000000000..e02cd5560
--- /dev/null
+++ b/src/blockchain_utilities/blockchain-stats-readme.md
@@ -0,0 +1,54 @@
+# Monero Blockchain Stats
+
+Monero Blockchain Stats utlity exports daily statistics for the monero blockchain from creation through current state.
+
+## Usage:
+
+See also the utility's help option. `monero-blockchain-stats --help`
+
+From the command line run:
+
+`$ monero-blockchain-stats`
+
+This loads the existing blockchain and prints the results to the terminal. Default printed data includes Blocks per Day, Total Blocks, Transactions per Day, Total Transactions, Bytes per Day and Total Bytes. The format of the output is in tab delimited csv which is printed to the console. Piping the output of the command to a csv file allows for saving the output of the utilty to a file.
+i.e. `monero-blockchain-stats > stats.csv`
+
+### Options
+`--data-dir arg`
+to specify location of blockchain storage
+
+`--testnet`
+Run on testnet.
+
+`--stagenet`
+Run on stagenet.
+
+`--log-level arg`
+0-4 or categories
+
+`--block-start arg (=0)`
+start at block number
+
+`--block-stop arg (=0)`
+Stop at block number
+
+`--with-inputs`
+with input stats
+
+`--with-outputs`
+with output stats
+
+`--with-ringsize`
+with ringsize stats
+
+`--with-hours`
+with txns per hour
+
+`--with-emission`
+with coin emission
+
+`--with-fees`
+with txn fees
+
+`--with-diff`
+with difficulty
diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp
index 18a37434c..d53251fd3 100644
--- a/src/blockchain_utilities/blockchain_blackball.cpp
+++ b/src/blockchain_utilities/blockchain_blackball.cpp
@@ -388,9 +388,7 @@ static bool for_all_transactions(const std::string &filename, uint64_t &start_id
cryptonote::transaction_prefix tx;
blobdata bd;
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
- std::stringstream ss;
- ss << bd;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(bd)};
bool r = do_serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index df2662444..8d81ef54d 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -146,7 +146,7 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
if (!parse_and_validate_block_from_blob(b.block, block))
{
MERROR("Failed to parse block: "
- << epee::string_tools::pod_to_hex(get_blob_hash(b.block)));
+ << epee::string_tools::buff_to_hex_nodelimer(b.block));
core.cleanup_handle_incoming_blocks();
return 1;
}
@@ -177,8 +177,11 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
core.handle_incoming_tx(tx_blob, tvc, relay_method::block, true);
if(tvc.m_verifivation_failed)
{
- MERROR("transaction verification failed, tx_id = "
- << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob.blob)));
+ cryptonote::transaction transaction;
+ if (cryptonote::parse_and_validate_tx_from_blob(tx_blob.blob, transaction))
+ MERROR("Transaction verification failed, tx_id = " << cryptonote::get_transaction_hash(transaction));
+ else
+ MERROR("Transaction verification failed, transaction is unparsable");
core.cleanup_handle_incoming_blocks();
return 1;
}
@@ -192,8 +195,11 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
if(bvc.m_verifivation_failed)
{
- MERROR("Block verification failed, id = "
- << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)));
+ cryptonote::block block;
+ if (cryptonote::parse_and_validate_block_from_blob(block_entry.block, block))
+ MERROR("Block verification failed, id = " << cryptonote::get_block_hash(block));
+ else
+ MERROR("Block verification failed, block is unparsable");
core.cleanup_handle_incoming_blocks();
return 1;
}
diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt
index 445596a66..43af5023d 100644
--- a/src/blocks/CMakeLists.txt
+++ b/src/blocks/CMakeLists.txt
@@ -28,20 +28,32 @@
set(GENERATED_SOURCES "")
+set(GENERATOR "${CMAKE_CURRENT_BINARY_DIR}/blocks_generator.cmake")
+file(GENERATE OUTPUT ${GENERATOR} CONTENT [=[
+file(READ "${INPUT_DAT_FILE}" DATA HEX)
+string(REGEX REPLACE "[0-9a-fA-F][0-9a-fA-F]" "0x\\0," DATA "${DATA}")
+file(WRITE "${OUTPUT_C_SOURCE}" "
+#include <stddef.h>
+const unsigned char ${BLOB_NAME}[]={
+ ${DATA}
+};
+const size_t ${BLOB_NAME}_len = sizeof(${BLOB_NAME});
+"
+)
+]=])
foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks)
set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c")
list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE})
set(INPUT_DAT_FILE "${BLOB_NAME}.dat")
add_custom_command(
- OUTPUT ${OUTPUT_C_SOURCE}
- MAIN_DEPENDENCY ${INPUT_DAT_FILE}
- COMMAND
- cd ${CMAKE_CURRENT_BINARY_DIR} &&
- echo "'#include\t<stddef.h>'" > ${OUTPUT_C_SOURCE} &&
- echo "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} &&
- od -v -An -tx1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "'s/[0-9a-fA-F]\\{1,\\}/0x&,/g'" -e "'$$s/.$$//'" >> ${OUTPUT_C_SOURCE} &&
- echo "'};'" >> ${OUTPUT_C_SOURCE} &&
- echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE}
+ OUTPUT ${OUTPUT_C_SOURCE}
+ MAIN_DEPENDENCY ${INPUT_DAT_FILE}
+ DEPENDS ${GENERATOR}
+ COMMAND ${CMAKE_COMMAND}
+ "-DINPUT_DAT_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE}"
+ "-DBLOB_NAME=${BLOB_NAME}"
+ "-DOUTPUT_C_SOURCE=${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_C_SOURCE}"
+ "-P${GENERATOR}"
)
endforeach()
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
index c9fb1433c..e386ec4ea 100644
--- a/src/cryptonote_basic/CMakeLists.txt
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -36,6 +36,14 @@ if(APPLE)
endif()
endif()
+monero_add_library(cryptonote_format_utils_basic
+ cryptonote_format_utils_basic.cpp
+)
+target_link_libraries(cryptonote_format_utils_basic
+ PUBLIC
+ cncrypto
+)
+
set(cryptonote_basic_sources
account.cpp
connection_context.cpp
@@ -74,6 +82,7 @@ target_link_libraries(cryptonote_basic
common
cncrypto
checkpoints
+ cryptonote_format_utils_basic
device
${Boost_DATE_TIME_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h
index c70ae1df1..6394a7071 100644
--- a/src/cryptonote_basic/cryptonote_basic.h
+++ b/src/cryptonote_basic/cryptonote_basic.h
@@ -152,10 +152,6 @@ namespace cryptonote
};
- template<typename T> static inline unsigned int getpos(T &ar) { return 0; }
- template<> inline unsigned int getpos(binary_archive<true> &ar) { return ar.stream().tellp(); }
- template<> inline unsigned int getpos(binary_archive<false> &ar) { return ar.stream().tellg(); }
-
class transaction_prefix
{
@@ -236,17 +232,17 @@ namespace cryptonote
set_blob_size_valid(false);
}
- const unsigned int start_pos = getpos(ar);
+ const auto start_pos = ar.getpos();
FIELDS(*static_cast<transaction_prefix *>(this))
if (std::is_same<Archive<W>, binary_archive<W>>())
- prefix_size = getpos(ar) - start_pos;
+ prefix_size = ar.getpos() - start_pos;
if (version == 1)
{
if (std::is_same<Archive<W>, binary_archive<W>>())
- unprunable_size = getpos(ar) - start_pos;
+ unprunable_size = ar.getpos() - start_pos;
ar.tag("signatures");
ar.begin_array();
@@ -284,11 +280,11 @@ namespace cryptonote
{
ar.begin_object();
bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
- if (!r || !ar.stream().good()) return false;
+ if (!r || !ar.good()) return false;
ar.end_object();
if (std::is_same<Archive<W>, binary_archive<W>>())
- unprunable_size = getpos(ar) - start_pos;
+ unprunable_size = ar.getpos() - start_pos;
if (!pruned && rct_signatures.type != rct::RCTTypeNull)
{
@@ -296,7 +292,7 @@ namespace cryptonote
ar.begin_object();
r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(),
vin.size() > 0 && vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
- if (!r || !ar.stream().good()) return false;
+ if (!r || !ar.good()) return false;
ar.end_object();
}
}
@@ -320,13 +316,13 @@ namespace cryptonote
{
ar.begin_object();
bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
- if (!r || !ar.stream().good()) return false;
+ if (!r || !ar.good()) return false;
ar.end_object();
}
}
if (!typename Archive<W>::is_saving())
pruned = true;
- return ar.stream().good();
+ return ar.good();
}
private:
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index b0c4a25d8..17adcdc35 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -139,22 +139,6 @@ namespace cryptonote
return h;
}
- //---------------------------------------------------------------
- void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h)
- {
- std::ostringstream s;
- binary_archive<true> a(s);
- ::serialization::serialize(a, const_cast<transaction_prefix&>(tx));
- crypto::cn_fast_hash(s.str().data(), s.str().size(), h);
- }
- //---------------------------------------------------------------
- crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx)
- {
- crypto::hash h = null_hash;
- get_transaction_prefix_hash(tx, h);
- return h;
- }
- //---------------------------------------------------------------
bool expand_transaction_1(transaction &tx, bool base_only)
{
if (tx.version >= 2 && !is_coinbase(tx))
@@ -211,9 +195,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx)
{
- std::stringstream ss;
- ss << tx_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(tx_blob)};
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
@@ -224,9 +206,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx)
{
- std::stringstream ss;
- ss << tx_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(tx_blob)};
bool r = tx.serialize_base(ba);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data");
@@ -236,9 +216,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool parse_and_validate_tx_prefix_from_blob(const blobdata_ref& tx_blob, transaction_prefix& tx)
{
- std::stringstream ss;
- ss << tx_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(tx_blob)};
bool r = ::serialization::serialize_noeof(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction prefix from blob");
return true;
@@ -246,9 +224,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash)
{
- std::stringstream ss;
- ss << tx_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(tx_blob)};
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
@@ -532,22 +508,15 @@ namespace cryptonote
if(tx_extra.empty())
return true;
- std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
- std::istringstream iss(extra_str);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::to_span(tx_extra)};
- bool eof = false;
- while (!eof)
+ do
{
tx_extra_field field;
bool r = ::do_serialize(ar, field);
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
tx_extra_fields.push_back(field);
-
- std::ios_base::iostate state = iss.rdstate();
- eof = (EOF == iss.peek());
- iss.clear(state);
- }
+ } while (!ar.eof());
CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
return true;
@@ -578,13 +547,10 @@ namespace cryptonote
return true;
}
- std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
- std::istringstream iss(extra_str);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::to_span(tx_extra)};
- bool eof = false;
size_t processed = 0;
- while (!eof)
+ do
{
tx_extra_field field;
bool r = ::do_serialize(ar, field);
@@ -596,12 +562,8 @@ namespace cryptonote
break;
}
tx_extra_fields.push_back(field);
- processed = iss.tellg();
-
- std::ios_base::iostate state = iss.rdstate();
- eof = (EOF == iss.peek());
- iss.clear(state);
- }
+ processed = ar.getpos();
+ } while (!ar.eof());
if (!::serialization::check_stream_state(ar))
{
MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
@@ -752,24 +714,18 @@ namespace cryptonote
if (tx_extra.empty())
return true;
std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
- std::istringstream iss(extra_str);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(extra_str)};
std::ostringstream oss;
binary_archive<true> newar(oss);
- bool eof = false;
- while (!eof)
+ do
{
tx_extra_field field;
bool r = ::do_serialize(ar, field);
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
if (field.type() != type)
::do_serialize(newar, field);
-
- std::ios_base::iostate state = iss.rdstate();
- eof = (EOF == iss.peek());
- iss.clear(state);
- }
+ } while (!ar.eof());
CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
tx_extra.clear();
std::string s = oss.str();
@@ -1357,9 +1313,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash)
{
- std::stringstream ss;
- ss << b_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(b_blob)};
bool r = ::serialization::serialize(ba, b);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob");
b.invalidate_hashes();
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index b311bd2b2..3fe4c44e7 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -148,9 +148,7 @@ namespace cryptonote
template<class t_object>
bool t_serializable_object_from_blob(t_object& to, const blobdata& b_blob)
{
- std::stringstream ss;
- ss << b_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{epee::strspan<std::uint8_t>(b_blob)};
bool r = ::serialization::serialize(ba, to);
return r;
}
diff --git a/src/cryptonote_basic/cryptonote_format_utils_basic.cpp b/src/cryptonote_basic/cryptonote_format_utils_basic.cpp
new file mode 100644
index 000000000..29130ce46
--- /dev/null
+++ b/src/cryptonote_basic/cryptonote_format_utils_basic.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2014-2021, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#include "cryptonote_format_utils.h"
+
+namespace cryptonote
+{
+ void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h)
+ {
+ std::ostringstream s;
+ binary_archive<true> a(s);
+ ::serialization::serialize(a, const_cast<transaction_prefix&>(tx));
+ crypto::cn_fast_hash(s.str().data(), s.str().size(), h);
+ }
+
+ crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx)
+ {
+ crypto::hash h = crypto::null_hash;
+ get_transaction_prefix_hash(tx, h);
+ return h;
+ }
+}
diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h
index 50f2e1438..76efc22d3 100644
--- a/src/cryptonote_basic/tx_extra.h
+++ b/src/cryptonote_basic/tx_extra.h
@@ -57,11 +57,7 @@ namespace cryptonote
// size - 1 - because of variant tag
for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size)
{
- std::ios_base::iostate state = ar.stream().rdstate();
- bool eof = EOF == ar.stream().peek();
- ar.stream().clear(state);
-
- if (eof)
+ if (ar.eof())
break;
uint8_t zero;
@@ -139,8 +135,7 @@ namespace cryptonote
if(!::do_serialize(ar, field))
return false;
- std::istringstream iss(field);
- binary_archive<false> iar(iss);
+ binary_archive<false> iar{epee::strspan<std::uint8_t>(field)};
serialize_helper helper(*this);
return ::serialization::serialize(iar, helper);
}
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index e0335a814..f0e6794b9 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -566,6 +566,8 @@ void Blockchain::pop_blocks(uint64_t nblocks)
return;
}
+ CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit");
+
if (stop_batch)
m_db->batch_stop();
}
@@ -643,7 +645,6 @@ block Blockchain::pop_block_from_blockchain()
m_scan_table.clear();
m_blocks_txs_check.clear();
- CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit");
uint64_t top_block_height;
crypto::hash top_block_hash = get_tail_id(top_block_height);
m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
@@ -966,7 +967,7 @@ start:
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");
+ MGINFO("Please send moneromooo on Libera.Chat the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
}
return diff;
}
@@ -1110,6 +1111,7 @@ bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
{
pop_block_from_blockchain();
}
+ CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit");
// make sure the hard fork object updates its current version
m_hardfork->reorganize_from_chain_height(rollback_height);
@@ -1160,6 +1162,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
block b = pop_block_from_blockchain();
disconnected_chain.push_front(b);
}
+ CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit");
auto split_height = m_db->height();
@@ -2609,7 +2612,7 @@ bool Blockchain::get_split_transactions_blobs(const t_ids_container& txs_ids, t_
}
//------------------------------------------------------------------
template<class t_ids_container, class t_tx_container, class t_missed_container>
-bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const
+bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool pruned) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
@@ -2620,10 +2623,12 @@ bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container
try
{
cryptonote::blobdata tx;
- if (m_db->get_tx_blob(tx_hash, tx))
+ bool res = pruned ? m_db->get_pruned_tx_blob(tx_hash, tx) : m_db->get_tx_blob(tx_hash, tx);
+ if (res)
{
txs.push_back(transaction());
- if (!parse_and_validate_tx_from_blob(tx, txs.back()))
+ res = pruned ? parse_and_validate_tx_base_from_blob(tx, txs.back()) : parse_and_validate_tx_from_blob(tx, txs.back());
+ if (!res)
{
LOG_ERROR("Invalid transaction");
return false;
@@ -5527,6 +5532,6 @@ void Blockchain::cache_block_template(const block &b, const cryptonote::account_
}
namespace cryptonote {
-template bool Blockchain::get_transactions(const std::vector<crypto::hash>&, std::vector<transaction>&, std::vector<crypto::hash>&) const;
+template bool Blockchain::get_transactions(const std::vector<crypto::hash>&, std::vector<transaction>&, std::vector<crypto::hash>&, bool) const;
template bool Blockchain::get_split_transactions_blobs(const std::vector<crypto::hash>&, std::vector<std::tuple<crypto::hash, cryptonote::blobdata, crypto::hash, cryptonote::blobdata>>&, std::vector<crypto::hash>&) const;
}
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 5291f1338..a0e7967de 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -721,7 +721,7 @@ namespace cryptonote
template<class t_ids_container, class t_tx_container, class t_missed_container>
bool get_split_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const;
template<class t_ids_container, class t_tx_container, class t_missed_container>
- bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const;
+ bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool pruned = false) const;
//debug functions
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index beae55b35..1da14221a 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -429,9 +429,9 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
- bool core::get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::blobdata>& txs, std::vector<crypto::hash>& missed_txs) const
+ bool core::get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::blobdata>& txs, std::vector<crypto::hash>& missed_txs, bool pruned) const
{
- return m_blockchain_storage.get_transactions_blobs(txs_ids, txs, missed_txs);
+ return m_blockchain_storage.get_transactions_blobs(txs_ids, txs, missed_txs, pruned);
}
//-----------------------------------------------------------------------------------------------
bool core::get_split_transactions_blobs(const std::vector<crypto::hash>& txs_ids, std::vector<std::tuple<crypto::hash, cryptonote::blobdata, crypto::hash, cryptonote::blobdata>>& txs, std::vector<crypto::hash>& missed_txs) const
@@ -445,9 +445,9 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
- bool core::get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<transaction>& txs, std::vector<crypto::hash>& missed_txs) const
+ bool core::get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<transaction>& txs, std::vector<crypto::hash>& missed_txs, bool pruned) const
{
- return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs);
+ return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs, pruned);
}
//-----------------------------------------------------------------------------------------------
bool core::get_alternative_blocks(std::vector<block>& blocks) const
@@ -1243,7 +1243,7 @@ namespace cryptonote
std::vector<transaction> txs;
std::vector<crypto::hash> missed_txs;
uint64_t coinbase_amount = get_outs_money_amount(b.miner_tx);
- this->get_transactions(b.tx_hashes, txs, missed_txs);
+ this->get_transactions(b.tx_hashes, txs, missed_txs, true);
uint64_t tx_fee_amount = 0;
for(const auto& tx: txs)
{
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 8891540a9..8478049f9 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -385,7 +385,7 @@ namespace cryptonote
*
* @note see Blockchain::get_transactions
*/
- bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::blobdata>& txs, std::vector<crypto::hash>& missed_txs) const;
+ bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::blobdata>& txs, std::vector<crypto::hash>& missed_txs, bool pruned = false) const;
/**
* @copydoc Blockchain::get_transactions
@@ -399,7 +399,7 @@ namespace cryptonote
*
* @note see Blockchain::get_transactions
*/
- bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<transaction>& txs, std::vector<crypto::hash>& missed_txs) const;
+ bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<transaction>& txs, std::vector<crypto::hash>& missed_txs, bool pruned = false) const;
/**
* @copydoc Blockchain::get_block_by_hash
diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt
index ff2afba4b..3597ab336 100644
--- a/src/device/CMakeLists.txt
+++ b/src/device/CMakeLists.txt
@@ -71,6 +71,7 @@ target_link_libraries(device
PUBLIC
${HIDAPI_LIBRARIES}
cncrypto
+ cryptonote_format_utils_basic
ringct_basic
wallet-crypto
${OPENSSL_CRYPTO_LIBRARIES}
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 26a0d8da5..5caad3a1a 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -518,9 +518,7 @@ namespace hw {
}
bool device_ledger::init(void) {
- #ifdef DEBUG_HWDEVICE
this->controle_device = &hw::get_device("default");
- #endif
this->release();
hw_device.init();
MDEBUG( "Device "<<this->id <<" HIDUSB inited");
@@ -738,6 +736,12 @@ namespace hw {
}
crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
+ if (has_view_key) {
+ cryptonote::account_keys keys_{keys};
+ keys_.m_view_secret_key = this->viewkey;
+ return this->controle_device->get_subaddress_spend_public_key(keys_, index);
+ }
+
AUTO_LOCK_CMD();
crypto::public_key D;
@@ -789,6 +793,12 @@ namespace hw {
}
cryptonote::account_public_address device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
+ if (has_view_key) {
+ cryptonote::account_keys keys_{keys};
+ keys_.m_view_secret_key = this->viewkey;
+ return this->controle_device->get_subaddress(keys_, index);
+ }
+
AUTO_LOCK_CMD();
cryptonote::account_public_address address;
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 00ff05ec5..3b6cc505f 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -181,11 +181,8 @@ namespace hw {
// To speed up blockchain parsing the view key maybe handle here.
crypto::secret_key viewkey;
bool has_view_key;
-
- //extra debug
- #ifdef DEBUG_HWDEVICE
+
device *controle_device;
- #endif
public:
device_ledger();
diff --git a/src/device_trezor/trezor/protocol.hpp b/src/device_trezor/trezor/protocol.hpp
index fa824ec3b..0fdd36a51 100644
--- a/src/device_trezor/trezor/protocol.hpp
+++ b/src/device_trezor/trezor/protocol.hpp
@@ -66,9 +66,7 @@ namespace protocol{
template<typename T>
bool cn_deserialize(const void * buff, size_t len, T & dst){
- std::stringstream ss;
- ss.write(static_cast<const char *>(buff), len); //ss << tx_blob;
- binary_archive<false> ba(ss);
+ binary_archive<false> ba{{reinterpret_cast<const std::uint8_t*>(buff), len}};
bool r = ::serialization::serialize(ba, dst);
return r;
}
diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp
index 194176413..881848a80 100644
--- a/src/device_trezor/trezor/transport.cpp
+++ b/src/device_trezor/trezor/transport.cpp
@@ -157,7 +157,11 @@ namespace trezor{
#define PROTO_HEADER_SIZE 6
static size_t message_size(const google::protobuf::Message &req){
+#if GOOGLE_PROTOBUF_VERSION < 3006001
+ return size_t(req.ByteSize());
+#else
return req.ByteSizeLong();
+#endif
}
static size_t serialize_message_buffer_size(size_t msg_size) {
@@ -573,8 +577,13 @@ namespace trezor{
std::string req = "PINGPING";
char res[8];
- m_socket->send_to(boost::asio::buffer(req.c_str(), req.size()), m_endpoint);
- receive(res, 8, nullptr, false, timeout);
+ const auto written = m_socket->send_to(boost::asio::buffer(req.c_str(), req.size()), m_endpoint);
+ if (written != req.size())
+ return false;
+ memset(res, 0, sizeof(res));
+ const auto received = receive(res, 8, nullptr, false, timeout);
+ if (received != 8)
+ return false;
return memcmp(res, "PONGPONG", 8) == 0;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index a0b8438b2..8dd4b4476 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -683,12 +683,14 @@ namespace nodetool
full_addrs.insert("212.83.172.165:28080");
full_addrs.insert("192.110.160.146:28080");
full_addrs.insert("88.99.173.38:28080");
+ full_addrs.insert("51.79.173.165:28080");
}
else if (m_nettype == cryptonote::STAGENET)
{
full_addrs.insert("162.210.173.150:38080");
full_addrs.insert("192.110.160.146:38080");
full_addrs.insert("88.99.173.38:38080");
+ full_addrs.insert("51.79.173.165:38080");
}
else if (m_nettype == cryptonote::FAKECHAIN)
{
@@ -704,6 +706,7 @@ namespace nodetool
full_addrs.insert("104.238.221.81:18080");
full_addrs.insert("66.85.74.134:18080");
full_addrs.insert("88.99.173.38:18080");
+ full_addrs.insert("51.79.173.165:18080");
}
return full_addrs;
}
@@ -831,6 +834,7 @@ namespace nodetool
"xwvz3ekocr3dkyxfkmgm2hvbpzx2ysqmaxgter7znnqrhoicygkfswid.onion:18083",
"4pixvbejrvihnkxmduo2agsnmc3rrulrqc7s3cbwwrep6h6hrzsibeqd.onion:18083",
"zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083",
+ "qz43zul2x56jexzoqgkx2trzwcfnr6l3hbtfcfx54g4r3eahy3bssjyd.onion:18083",
};
}
return {};
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index 00b72123a..278ff4164 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -284,7 +284,7 @@ namespace rct {
{
FIELD(type)
if (type == RCTTypeNull)
- return ar.stream().good();
+ return ar.good();
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG)
return false;
VARINT_FIELD(txnFee)
@@ -344,7 +344,7 @@ namespace rct {
ar.delimit_array();
}
ar.end_array();
- return ar.stream().good();
+ return ar.good();
}
BEGIN_SERIALIZE_OBJECT()
@@ -375,7 +375,7 @@ namespace rct {
if (mixin >= 0xffffffff)
return false;
if (type == RCTTypeNull)
- return ar.stream().good();
+ return ar.good();
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG)
return false;
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
@@ -522,7 +522,7 @@ namespace rct {
}
ar.end_array();
}
- return ar.stream().good();
+ return ar.good();
}
BEGIN_SERIALIZE_OBJECT()
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index ded545efa..8d8a68efb 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1044,6 +1044,7 @@ namespace cryptonote
if (e.in_pool)
{
e.block_height = e.block_timestamp = std::numeric_limits<uint64_t>::max();
+ e.confirmations = 0;
auto it = per_tx_pool_tx_info.find(tx_hash);
if (it != per_tx_pool_tx_info.end())
{
@@ -1062,6 +1063,7 @@ namespace cryptonote
else
{
e.block_height = m_core.get_blockchain_storage().get_db().get_tx_block_height(tx_hash);
+ e.confirmations = m_core.get_current_blockchain_height() - e.block_height;
e.block_timestamp = m_core.get_blockchain_storage().get_db().get_block_timestamp(e.block_height);
e.received_timestamp = 0;
e.double_spend_seen = false;
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 5ebe4f654..ff8c98b98 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -88,7 +88,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 3
-#define CORE_RPC_VERSION_MINOR 6
+#define CORE_RPC_VERSION_MINOR 7
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -350,6 +350,7 @@ namespace cryptonote
bool in_pool;
bool double_spend_seen;
uint64_t block_height;
+ uint64_t confirmations;
uint64_t block_timestamp;
uint64_t received_timestamp;
std::vector<uint64_t> output_indices;
@@ -367,6 +368,7 @@ namespace cryptonote
if (!this_ref.in_pool)
{
KV_SERIALIZE(block_height)
+ KV_SERIALIZE(confirmations)
KV_SERIALIZE(block_timestamp)
KV_SERIALIZE(output_indices)
}
diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp
index bf6584f72..f0c513911 100644
--- a/src/rpc/rpc_payment.cpp
+++ b/src/rpc/rpc_payment.cpp
@@ -293,12 +293,13 @@ namespace cryptonote
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);
+ std::string bytes(std::istream_iterator<char>{data}, std::istream_iterator<char>{});
if (!data.fail())
{
bool loaded = false;
try
{
- binary_archive<false> ar(data);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(bytes)};
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -306,6 +307,8 @@ namespace cryptonote
catch (...) {}
if (!loaded)
{
+ bytes.clear();
+ bytes.shrink_to_fit();
try
{
boost::archive::portable_binary_iarchive a(data);
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h
index 49ca8aa57..acda70039 100644
--- a/src/serialization/binary_archive.h
+++ b/src/serialization/binary_archive.h
@@ -36,9 +36,11 @@
#include <cassert>
#include <iostream>
#include <iterator>
+#include <boost/endian/conversion.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include "common/varint.h"
+#include "span.h"
#include "warnings.h"
/* I have no clue what these lines means */
@@ -55,16 +57,15 @@ DISABLE_VS_WARNINGS(4244)
* purpse is to define the functions used for the binary_archive. Its
* a header, basically. I think it was declared simply to save typing...
*/
-template <class Stream, bool IsSaving>
+template <bool IsSaving>
struct binary_archive_base
{
- typedef Stream stream_type;
- typedef binary_archive_base<Stream, IsSaving> base_type;
+ typedef binary_archive_base<IsSaving> base_type;
typedef boost::mpl::bool_<IsSaving> is_saving;
typedef uint8_t variant_tag_type;
- explicit binary_archive_base(stream_type &s) : stream_(s) { }
+ explicit binary_archive_base() { }
/* definition of standard API functions */
void tag(const char *) { }
@@ -72,12 +73,6 @@ struct binary_archive_base
void end_object() { }
void begin_variant() { }
void end_variant() { }
- /* I just want to leave a comment saying how this line really shows
- flaws in the ownership model of many OOP languages, that is all. */
- stream_type &stream() { return stream_; }
-
-protected:
- stream_type &stream_;
};
/* \struct binary_archive
@@ -95,15 +90,18 @@ struct binary_archive;
template <>
-struct binary_archive<false> : public binary_archive_base<std::istream, false>
+struct binary_archive<false> : public binary_archive_base<false>
{
+ explicit binary_archive(epee::span<const std::uint8_t> s)
+ : base_type(), bytes_(s), begin_(s.begin()), good_(true), varint_bug_backward_compatibility_(false)
+ {}
- explicit binary_archive(stream_type &s) : base_type(s), varint_bug_backward_compatibility_(false) {
- stream_type::pos_type pos = stream_.tellg();
- stream_.seekg(0, std::ios_base::end);
- eof_pos_ = stream_.tellg();
- stream_.seekg(pos);
- }
+ bool good() const noexcept { return good_; }
+ void set_fail() noexcept { good_ = false; }
+
+ //! If implementing as `std::istream`, reset stream error state after `peek()` call.
+ bool eof() const noexcept { return bytes_.empty(); }
+ std::size_t getpos() const noexcept { return bytes_.begin() - begin_; }
template <class T>
void serialize_int(T &v)
@@ -116,24 +114,24 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
* \brief serializes an unsigned integer
*/
template <class T>
- void serialize_uint(T &v, size_t width = sizeof(T))
+ void serialize_uint(T &v)
{
- T ret = 0;
- unsigned shift = 0;
- for (size_t i = 0; i < width; i++) {
- //std::cerr << "tell: " << stream_.tellg() << " value: " << ret << std::endl;
- char c;
- stream_.get(c);
- T b = (unsigned char)c;
- ret += (b << shift); // can this be changed to OR, i think it can.
- shift += 8;
+ const std::size_t actual = bytes_.remove_prefix(sizeof(T));
+ good_ &= (actual == sizeof(T));
+ if (actual == sizeof(T))
+ {
+ std::memcpy(std::addressof(v), bytes_.data() - sizeof(T), sizeof(T));
+ boost::endian::little_to_native_inplace(v); // epee isn't templated
}
- v = ret;
+ else
+ v = 0; // ensures initialization
}
void serialize_blob(void *buf, size_t len, const char *delimiter="")
{
- stream_.read((char *)buf, len);
+ const std::size_t actual = bytes_.remove_prefix(len);
+ good_ &= (len == actual);
+ std::memcpy(buf, bytes_.data() - actual, actual);
}
template <class T>
@@ -145,9 +143,11 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
template <class T>
void serialize_uvarint(T &v)
{
- typedef std::istreambuf_iterator<char> it;
- if (tools::read_varint(it(stream_), it(), v) < 0)
- stream_.setstate(std::ios_base::failbit);
+ auto current = bytes_.cbegin();
+ auto end = bytes_.cend();
+ good_ &= (0 <= tools::read_varint(current, end, v));
+ current = std::min(current, bytes_.cend());
+ bytes_ = {current, std::size_t(bytes_.cend() - current)};
}
void begin_array(size_t &s)
@@ -166,26 +166,26 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
serialize_int(t);
}
- size_t remaining_bytes() {
- if (!stream_.good())
- return 0;
- //std::cerr << "tell: " << stream_.tellg() << std::endl;
- assert(stream_.tellg() <= eof_pos_);
- return eof_pos_ - stream_.tellg();
- }
-
+ size_t remaining_bytes() const noexcept { return good() ? bytes_.size() : 0; }
void enable_varint_bug_backward_compatibility() { varint_bug_backward_compatibility_ = true; }
bool varint_bug_backward_compatibility_enabled() const { return varint_bug_backward_compatibility_; }
-
protected:
- std::streamoff eof_pos_;
+ epee::span<const std::uint8_t> bytes_;
+ std::uint8_t const* const begin_;
+ bool good_;
bool varint_bug_backward_compatibility_;
};
template <>
-struct binary_archive<true> : public binary_archive_base<std::ostream, true>
+struct binary_archive<true> : public binary_archive_base<true>
{
- explicit binary_archive(stream_type &s) : base_type(s) { }
+ typedef std::ostream stream_type;
+ explicit binary_archive(stream_type &s) : base_type(), stream_(s) { }
+
+ bool good() const { return stream_.good(); }
+ void set_fail() { stream_.setstate(std::ios::failbit); }
+
+ std::streampos getpos() const { return stream_.tellp(); }
template <class T>
void serialize_int(T v)
@@ -234,6 +234,8 @@ struct binary_archive<true> : public binary_archive_base<std::ostream, true>
}
bool varint_bug_backward_compatibility_enabled() const { return false; }
+protected:
+ stream_type& stream_;
};
POP_WARNINGS
diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h
index 8635585af..8444f220e 100644
--- a/src/serialization/binary_utils.h
+++ b/src/serialization/binary_utils.h
@@ -39,8 +39,7 @@ namespace serialization {
template <class T>
bool parse_binary(const std::string &blob, T &v)
{
- std::istringstream istr(blob);
- binary_archive<false> iar(istr);
+ binary_archive<false> iar{epee::strspan<std::uint8_t>(blob)};
return ::serialization::serialize(iar, v);
}
diff --git a/src/serialization/container.h b/src/serialization/container.h
index a4997c8ae..77681ec93 100644
--- a/src/serialization/container.h
+++ b/src/serialization/container.h
@@ -67,13 +67,13 @@ bool do_serialize_container(Archive<false> &ar, C &v)
{
size_t cnt;
ar.begin_array(cnt);
- if (!ar.stream().good())
+ if (!ar.good())
return false;
v.clear();
// very basic sanity check
if (ar.remaining_bytes() < cnt) {
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
@@ -86,7 +86,7 @@ bool do_serialize_container(Archive<false> &ar, C &v)
if (!::serialization::detail::serialize_container_element(ar, e))
return false;
::serialization::detail::do_add(v, std::move(e));
- if (!ar.stream().good())
+ if (!ar.good())
return false;
}
ar.end_array();
@@ -100,13 +100,13 @@ bool do_serialize_container(Archive<true> &ar, C &v)
ar.begin_array(cnt);
for (auto i = v.begin(); i != v.end(); ++i)
{
- if (!ar.stream().good())
+ if (!ar.good())
return false;
if (i != v.begin())
ar.delimit_array();
if(!::serialization::detail::serialize_container_element(ar, (typename C::value_type&)*i))
return false;
- if (!ar.stream().good())
+ if (!ar.good())
return false;
}
ar.end_array();
diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h
index 42bd06e92..d635a9ee9 100644
--- a/src/serialization/crypto.h
+++ b/src/serialization/crypto.h
@@ -47,7 +47,7 @@ bool do_serialize(Archive<false> &ar, std::vector<crypto::signature> &v)
// very basic sanity check
if (ar.remaining_bytes() < cnt*sizeof(crypto::signature)) {
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
@@ -55,7 +55,7 @@ bool do_serialize(Archive<false> &ar, std::vector<crypto::signature> &v)
for (size_t i = 0; i < cnt; i++) {
v.resize(i+1);
ar.serialize_blob(&(v[i]), sizeof(crypto::signature), "");
- if (!ar.stream().good())
+ if (!ar.good())
return false;
}
return true;
@@ -70,7 +70,7 @@ bool do_serialize(Archive<true> &ar, std::vector<crypto::signature> &v)
size_t cnt = v.size();
for (size_t i = 0; i < cnt; i++) {
ar.serialize_blob(&(v[i]), sizeof(crypto::signature), "");
- if (!ar.stream().good())
+ if (!ar.good())
return false;
}
ar.end_string();
diff --git a/src/serialization/debug_archive.h b/src/serialization/debug_archive.h
index b04d6ae19..e8ccb9a58 100644
--- a/src/serialization/debug_archive.h
+++ b/src/serialization/debug_archive.h
@@ -38,6 +38,7 @@ struct debug_archive : public json_archive<W> {
typedef typename json_archive<W>::stream_type stream_type;
debug_archive(stream_type &s) : json_archive<W>(s) { }
+ stream_type& stream() { return this->stream_; }
};
template <class T>
diff --git a/src/serialization/difficulty_type.h b/src/serialization/difficulty_type.h
index 56c0312e7..75d1fd13f 100644
--- a/src/serialization/difficulty_type.h
+++ b/src/serialization/difficulty_type.h
@@ -38,10 +38,10 @@ inline bool do_serialize(Archive<false>& ar, cryptonote::difficulty_type &diff)
{
uint64_t hi, lo;
ar.serialize_varint(hi);
- if (!ar.stream().good())
+ if (!ar.good())
return false;
ar.serialize_varint(lo);
- if (!ar.stream().good())
+ if (!ar.good())
return false;
diff = hi;
diff <<= 64;
@@ -52,13 +52,13 @@ inline bool do_serialize(Archive<false>& ar, cryptonote::difficulty_type &diff)
template <template <bool> class Archive>
inline bool do_serialize(Archive<true>& ar, cryptonote::difficulty_type &diff)
{
- if (!ar.stream().good())
+ if (!ar.good())
return false;
const uint64_t hi = ((diff >> 64) & 0xffffffffffffffff).convert_to<uint64_t>();
const uint64_t lo = (diff & 0xffffffffffffffff).convert_to<uint64_t>();
ar.serialize_varint(hi);
ar.serialize_varint(lo);
- if (!ar.stream().good())
+ if (!ar.good())
return false;
return true;
}
diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h
index 3f98b5101..bab6dfa94 100644
--- a/src/serialization/json_archive.h
+++ b/src/serialization/json_archive.h
@@ -58,6 +58,10 @@ struct json_archive_base
json_archive_base(stream_type &s, bool indent = false)
: stream_(s), indent_(indent), object_begin(false), depth_(0) { }
+ bool good() const { return stream_.good(); }
+ void set_fail() { stream_.setstate(std::ios::failbit); }
+ void clear_fail() { stream_.clear(); }
+
void tag(const char *tag) {
if (!object_begin)
stream_ << ", ";
@@ -82,7 +86,6 @@ struct json_archive_base
void begin_variant() { begin_object(); }
void end_variant() { end_object(); }
- Stream &stream() { return stream_; }
bool varint_bug_backward_compatibility_enabled() const { return false; }
@@ -117,6 +120,8 @@ struct json_archive<true> : public json_archive_base<std::ostream, true>
{
json_archive(stream_type &s, bool indent = false) : base_type(s, indent), inner_array_size_(0) { }
+ std::streampos getpos() const { return stream_.tellp(); }
+
template<typename T>
static auto promote_to_printable_integer_type(T v) -> decltype(+v)
{
diff --git a/src/serialization/pair.h b/src/serialization/pair.h
index 44aafa04d..2d9a89242 100644
--- a/src/serialization/pair.h
+++ b/src/serialization/pair.h
@@ -69,19 +69,19 @@ inline bool do_serialize(Archive<false>& ar, std::pair<F,S>& p)
{
size_t cnt;
ar.begin_array(cnt);
- if (!ar.stream().good())
+ if (!ar.good())
return false;
if (cnt != 2)
return false;
if (!::serialization::detail::serialize_pair_element(ar, p.first))
return false;
- if (!ar.stream().good())
+ if (!ar.good())
return false;
ar.delimit_array();
if (!::serialization::detail::serialize_pair_element(ar, p.second))
return false;
- if (!ar.stream().good())
+ if (!ar.good())
return false;
ar.end_array();
@@ -92,16 +92,16 @@ template <template <bool> class Archive, class F, class S>
inline bool do_serialize(Archive<true>& ar, std::pair<F,S>& p)
{
ar.begin_array(2);
- if (!ar.stream().good())
+ if (!ar.good())
return false;
if(!::serialization::detail::serialize_pair_element(ar, p.first))
return false;
- if (!ar.stream().good())
+ if (!ar.good())
return false;
ar.delimit_array();
if(!::serialization::detail::serialize_pair_element(ar, p.second))
return false;
- if (!ar.stream().good())
+ if (!ar.good())
return false;
ar.end_array();
return true;
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index 3ebeed171..4acadeab3 100644
--- a/src/serialization/serialization.h
+++ b/src/serialization/serialization.h
@@ -213,7 +213,7 @@ inline bool do_serialize(Archive &ar, bool &v)
* \brief self-explanatory
*/
#define END_SERIALIZE() \
- return ar.stream().good(); \
+ return ar.good(); \
}
/*! \macro VALUE(f)
@@ -223,7 +223,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag(#f); \
bool r = ::do_serialize(ar, f); \
- if (!r || !ar.stream().good()) return false; \
+ if (!r || !ar.good()) return false; \
} while(0);
/*! \macro FIELD_N(t,f)
@@ -234,7 +234,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag(t); \
bool r = ::do_serialize(ar, f); \
- if (!r || !ar.stream().good()) return false; \
+ if (!r || !ar.good()) return false; \
} while(0);
/*! \macro FIELD(f)
@@ -245,7 +245,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag(#f); \
bool r = ::do_serialize(ar, f); \
- if (!r || !ar.stream().good()) return false; \
+ if (!r || !ar.good()) return false; \
} while(0);
/*! \macro FIELDS(f)
@@ -255,7 +255,7 @@ inline bool do_serialize(Archive &ar, bool &v)
#define FIELDS(f) \
do { \
bool r = ::do_serialize(ar, f); \
- if (!r || !ar.stream().good()) return false; \
+ if (!r || !ar.good()) return false; \
} while(0);
/*! \macro VARINT_FIELD(f)
@@ -265,7 +265,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag(#f); \
ar.serialize_varint(f); \
- if (!ar.stream().good()) return false; \
+ if (!ar.good()) return false; \
} while(0);
/*! \macro VARINT_FIELD_N(t, f)
@@ -276,7 +276,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag(t); \
ar.serialize_varint(f); \
- if (!ar.stream().good()) return false; \
+ if (!ar.good()) return false; \
} while(0);
/*! \macro MAGIC_FIELD(m)
@@ -286,7 +286,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag("magic"); \
ar.serialize_blob((void*)magic.data(), magic.size()); \
- if (!ar.stream().good()) return false; \
+ if (!ar.good()) return false; \
if (magic != m) return false; \
} while(0);
@@ -297,7 +297,7 @@ inline bool do_serialize(Archive &ar, bool &v)
do { \
ar.tag("version"); \
ar.serialize_varint(version); \
- if (!ar.stream().good()) return false; \
+ if (!ar.good()) return false; \
} while(0);
@@ -339,10 +339,10 @@ namespace serialization {
*
* \brief self explanatory
*/
- template<class Stream>
- bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>, bool noeof)
+ template<class Archive>
+ bool do_check_stream_state(Archive& ar, boost::mpl::bool_<true>, bool noeof)
{
- return s.good();
+ return ar.good();
}
/*! \fn do_check_stream_state
*
@@ -350,15 +350,13 @@ namespace serialization {
*
* \detailed Also checks to make sure that the stream is not at EOF
*/
- template<class Stream>
- bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>, bool noeof)
+ template<class Archive>
+ bool do_check_stream_state(Archive& ar, boost::mpl::bool_<false>, bool noeof)
{
bool result = false;
- if (s.good())
+ if (ar.good())
{
- std::ios_base::iostate state = s.rdstate();
- result = noeof || EOF == s.peek();
- s.clear(state);
+ result = noeof || ar.eof();
}
return result;
}
@@ -371,7 +369,7 @@ namespace serialization {
template<class Archive>
bool check_stream_state(Archive& ar, bool noeof = false)
{
- return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving(), noeof);
+ return detail::do_check_stream_state(ar, typename Archive::is_saving(), noeof);
}
/*! \fn serialize
diff --git a/src/serialization/string.h b/src/serialization/string.h
index f5f69833a..f1f8f4ab0 100644
--- a/src/serialization/string.h
+++ b/src/serialization/string.h
@@ -39,7 +39,7 @@ inline bool do_serialize(Archive<false>& ar, std::string& str)
ar.serialize_varint(size);
if (ar.remaining_bytes() < size)
{
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
diff --git a/src/serialization/variant.h b/src/serialization/variant.h
index b08cf6bf0..6debb63d1 100644
--- a/src/serialization/variant.h
+++ b/src/serialization/variant.h
@@ -74,7 +74,7 @@ struct variant_reader
current_type x;
if(!::do_serialize(ar, x))
{
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
v = x;
@@ -95,7 +95,7 @@ struct variant_reader<Archive, Variant, TBegin, TBegin>
static inline bool read(Archive &ar, Variant &v, variant_tag_type t)
{
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
};
@@ -116,7 +116,7 @@ struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
typename boost::mpl::begin<types>::type,
typename boost::mpl::end<types>::type>::read(ar, v, t))
{
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
ar.end_variant();
@@ -143,7 +143,7 @@ struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
ar.write_variant_tag(variant_serialization_traits<Archive<true>, T>::get_tag());
if(!::do_serialize(ar, rv))
{
- ar.stream().setstate(std::ios::failbit);
+ ar.set_fail();
return false;
}
ar.end_variant();
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index e859a4693..dc031b36c 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -8922,12 +8922,12 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
// header
file <<
- boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%100.100s,%20.20s,%s,%s") %
+ boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s") %
tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note")
<< std::endl;
uint64_t running_balance = 0;
- auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%100.100s,%20.20s,\"%s\",%s");
+ auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s");
for (const auto& transfer : all_transfers)
{
diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt
index 30eb4ce03..655cdfefd 100644
--- a/src/wallet/api/CMakeLists.txt
+++ b/src/wallet/api/CMakeLists.txt
@@ -71,10 +71,13 @@ target_link_libraries(wallet_api
mnemonics
${LMDB_LIBRARY}
${Boost_CHRONO_LIBRARY}
+ ${Boost_LOCALE_LIBRARY}
+ ${ICU_LIBRARIES}
${Boost_SERIALIZATION_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
${Boost_REGEX_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp
index 96090d9f5..0b0e17464 100644
--- a/src/wallet/api/address_book.cpp
+++ b/src/wallet/api/address_book.cpp
@@ -81,7 +81,7 @@ bool AddressBookImpl::setDescription(std::size_t index, const std::string &descr
tools::wallet2::address_book_row entry = ab[index];
entry.m_description = description;
- bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, NULL, entry.m_description, entry.m_is_subaddress);
+ bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, entry.m_has_payment_id ? &entry.m_payment_id : nullptr, entry.m_description, entry.m_is_subaddress);
if (r)
refresh();
else
@@ -166,5 +166,3 @@ AddressBookImpl::~AddressBookImpl()
}
} // namespace
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h
index e22f474fb..40da46853 100644
--- a/src/wallet/api/address_book.h
+++ b/src/wallet/api/address_book.h
@@ -66,6 +66,3 @@ private:
};
}
-
-namespace Bitmonero = Monero;
-
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index b28ffd64c..f7e74591f 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -264,6 +264,3 @@ std::vector<std::string> PendingTransactionImpl::signersKeys() const {
}
}
-
-namespace Bitmonero = Monero;
-
diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
index bd0ca80a6..274c60851 100644
--- a/src/wallet/api/pending_transaction.h
+++ b/src/wallet/api/pending_transaction.h
@@ -73,5 +73,3 @@ private:
}
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index d8e4aab65..4649089ea 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -266,5 +266,3 @@ void TransactionHistoryImpl::refresh()
}
} // namespace
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h
index 60f12d771..fe77253e6 100644
--- a/src/wallet/api/transaction_history.h
+++ b/src/wallet/api/transaction_history.h
@@ -56,6 +56,3 @@ private:
};
}
-
-namespace Bitmonero = Monero;
-
diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp
index 33e7856db..edbdc469a 100644
--- a/src/wallet/api/transaction_info.cpp
+++ b/src/wallet/api/transaction_info.cpp
@@ -150,5 +150,3 @@ uint64_t TransactionInfoImpl::unlockTime() const
}
} // namespace
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h
index 8bc36a8e9..5eeeb04c2 100644
--- a/src/wallet/api/transaction_info.h
+++ b/src/wallet/api/transaction_info.h
@@ -87,5 +87,3 @@ private:
};
} // namespace
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index fb96674a7..4ccfafebd 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -316,6 +316,3 @@ uint64_t UnsignedTransactionImpl::minMixinCount() const
}
} // namespace
-
-namespace Bitmonero = Monero;
-
diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h
index 81fc098ff..07649e39e 100644
--- a/src/wallet/api/unsigned_transaction.h
+++ b/src/wallet/api/unsigned_transaction.h
@@ -71,5 +71,3 @@ private:
}
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/utils.cpp b/src/wallet/api/utils.cpp
index 34debee9d..19151b5f6 100644
--- a/src/wallet/api/utils.cpp
+++ b/src/wallet/api/utils.cpp
@@ -60,5 +60,3 @@ void onStartup()
} // namespace
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index db3049f9e..b4fa1ea8c 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -58,7 +58,6 @@ namespace Monero {
namespace {
// copy-pasted from simplewallet
- static const size_t DEFAULT_MIXIN = 6;
static const int DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10;
// limit maximum refresh interval as one minute
static const int MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1;
@@ -837,6 +836,11 @@ bool WalletImpl::setPassword(const std::string &password)
return status() == Status_Ok;
}
+const std::string& WalletImpl::getPassword() const
+{
+ return m_password;
+}
+
bool WalletImpl::setDevicePin(const std::string &pin)
{
clearStatus();
@@ -1176,7 +1180,7 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
try
{
- if (!m_wallet->export_key_images(filename), all)
+ if (!m_wallet->export_key_images(filename, all))
{
setStatusError(tr("failed to save file ") + filename);
return false;
@@ -1491,13 +1495,6 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
cryptonote::address_parse_info info;
- // indicates if dst_addr is integrated address (address + payment_id)
- // TODO: (https://bitcointalk.org/index.php?topic=753252.msg9985441#msg9985441)
- size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin();
- if (fake_outs_count == 0)
- fake_outs_count = DEFAULT_MIXIN;
- fake_outs_count = m_wallet->adjust_mixin(fake_outs_count);
-
uint32_t adjusted_priority = m_wallet->adjust_priority(static_cast<uint32_t>(priority));
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
@@ -1563,6 +1560,9 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
break;
}
try {
+ size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin();
+ fake_outs_count = m_wallet->adjust_mixin(mixin_count);
+
if (amount) {
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
adjusted_priority,
@@ -2063,9 +2063,24 @@ bool WalletImpl::checkReserveProof(const std::string &address, const std::string
}
}
-std::string WalletImpl::signMessage(const std::string &message)
+std::string WalletImpl::signMessage(const std::string &message, const std::string &address)
{
- return m_wallet->sign(message, tools::wallet2::sign_with_spend_key);
+ if (address.empty()) {
+ return m_wallet->sign(message, tools::wallet2::sign_with_spend_key);
+ }
+
+ cryptonote::address_parse_info info;
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address)) {
+ setStatusError(tr("Failed to parse address"));
+ return "";
+ }
+ auto index = m_wallet->get_subaddress_index(info.address);
+ if (!index) {
+ setStatusError(tr("Address doesn't belong to the wallet"));
+ return "";
+ }
+
+ return m_wallet->sign(message, tools::wallet2::sign_with_spend_key, *index);
}
bool WalletImpl::verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const
@@ -2576,6 +2591,32 @@ void WalletImpl::deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex,
m_wallet->device_show_address(accountIndex, addressIndex, payment_id_param);
}
-} // namespace
-namespace Bitmonero = Monero;
+bool WalletImpl::reconnectDevice()
+{
+ clearStatus();
+
+ bool r;
+ try {
+ r = m_wallet->reconnect_device();
+ }
+ catch (const std::exception &e) {
+ LOG_ERROR(__FUNCTION__ << " error: " << e.what());
+ setStatusError(e.what());
+ return false;
+ }
+
+ return r;
+}
+
+uint64_t WalletImpl::getBytesReceived()
+{
+ return m_wallet->get_bytes_received();
+}
+
+uint64_t WalletImpl::getBytesSent()
+{
+ return m_wallet->get_bytes_sent();
+}
+
+} // namespace
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index ce2d7d7e4..217f16e48 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -89,6 +89,7 @@ public:
std::string errorString() const override;
void statusWithErrorString(int& status, std::string& errorString) const override;
bool setPassword(const std::string &password) override;
+ const std::string& getPassword() const override;
bool setDevicePin(const std::string &password) override;
bool setDevicePassphrase(const std::string &password) override;
std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const override;
@@ -196,7 +197,7 @@ public:
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override;
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const override;
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override;
- virtual std::string signMessage(const std::string &message) override;
+ virtual std::string signMessage(const std::string &message, const std::string &address) override;
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override;
virtual std::string signMultisigParticipant(const std::string &message) const override;
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override;
@@ -220,6 +221,9 @@ public:
virtual bool isKeysFileLocked() override;
virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override;
virtual void deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) override;
+ virtual bool reconnectDevice() override;
+ virtual uint64_t getBytesReceived() override;
+ virtual uint64_t getBytesSent() override;
private:
void clearStatus() const;
@@ -281,7 +285,4 @@ private:
} // namespace
-namespace Bitmonero = Monero;
-
#endif
-
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index e34332734..a08033033 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -456,6 +456,7 @@ struct Wallet
//! returns both error and error string atomically. suggested to use in instead of status() and errorString()
virtual void statusWithErrorString(int& status, std::string& errorString) const = 0;
virtual bool setPassword(const std::string &password) = 0;
+ virtual const std::string& getPassword() const = 0;
virtual bool setDevicePin(const std::string &pin) { (void)pin; return false; };
virtual bool setDevicePassphrase(const std::string &passphrase) { (void)passphrase; return false; };
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
@@ -993,7 +994,7 @@ struct Wallet
* \param message - the message to sign (arbitrary byte data)
* \return the signature
*/
- virtual std::string signMessage(const std::string &message) = 0;
+ virtual std::string signMessage(const std::string &message, const std::string &address = "") = 0;
/*!
* \brief verifySignedMessage - verify a signature matches a given message
* \param message - the message (arbitrary byte data)
@@ -1084,6 +1085,15 @@ struct Wallet
//! shows address on device display
virtual void deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) = 0;
+
+ //! attempt to reconnect to hardware device
+ virtual bool reconnectDevice() = 0;
+
+ //! get bytes received
+ virtual uint64_t getBytesReceived() = 0;
+
+ //! get bytes sent
+ virtual uint64_t getBytesSent() = 0;
};
/**
@@ -1362,6 +1372,3 @@ struct WalletManagerFactory
}
-
-namespace Bitmonero = Monero;
-
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 900fe91e5..417a27db5 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -406,5 +406,3 @@ void WalletManagerFactory::setLogCategories(const std::string &categories)
}
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 2f603b0a9..cf3056a17 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -102,5 +102,3 @@ private:
};
} // namespace
-
-namespace Bitmonero = Monero;
diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp
index b7b29420b..34b4f440b 100644
--- a/src/wallet/message_store.cpp
+++ b/src/wallet/message_store.cpp
@@ -193,9 +193,7 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con
{
try
{
- std::stringstream iss;
- iss << signer_config;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(signer_config)};
THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, signers), tools::error::wallet_internal_error, "Failed to serialize signer config");
}
catch (...)
@@ -383,9 +381,7 @@ void message_store::process_auto_config_data_message(uint32_t id)
auto_config_data data;
try
{
- std::stringstream iss;
- iss << m.content;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(m.content)};
THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, data), tools::error::wallet_internal_error, "Failed to serialize auto config data");
}
catch (...)
@@ -790,9 +786,7 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std
file_data read_file_data;
try
{
- std::stringstream iss;
- iss << buf;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(buf)};
if (::serialization::serialize(ar, read_file_data))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -829,9 +823,7 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std
loaded = false;
try
{
- std::stringstream iss;
- iss << decrypted_data;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(decrypted_data)};
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 0b310111e..133db6c2a 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1320,6 +1320,9 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
m_trusted_daemon = trusted_daemon;
if (changed)
{
+ if (!m_persistent_rpc_client_id) {
+ set_rpc_client_secret_key(rct::rct2sk(rct::skGen()));
+ }
m_rpc_payment_state.expected_spent = 0;
m_rpc_payment_state.discrepancy = 0;
m_node_rpc_proxy.invalidate();
@@ -5701,17 +5704,13 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
try
{
- std::stringstream iss;
- iss << cache_data;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(cache_data)};
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
if (!loaded)
{
- std::stringstream iss;
- iss << cache_data;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(cache_data)};
ar.enable_varint_bug_backward_compatibility();
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
@@ -6786,8 +6785,7 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
catch(const std::exception &e) { LOG_PRINT_L0("Failed to decrypt unsigned tx: " << e.what()); return false; }
try
{
- std::istringstream iss(s);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(s)};
if (!::serialization::serialize(ar, exported_txs))
{
LOG_PRINT_L0("Failed to parse data from unsigned tx");
@@ -7101,8 +7099,7 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
catch (const std::exception &e) { LOG_PRINT_L0("Failed to decrypt signed transaction: " << e.what()); return false; }
try
{
- std::istringstream iss(s);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(s)};
if (!::serialization::serialize(ar, signed_txs))
{
LOG_PRINT_L0("Failed to deserialize signed transaction");
@@ -7237,8 +7234,7 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
bool loaded = false;
try
{
- std::istringstream iss(multisig_tx_st);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(multisig_tx_st)};
if (::serialization::serialize(ar, exported_txs))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -11516,6 +11512,9 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
{
+ uint32_t rpc_version;
+ THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address());
+
COMMAND_RPC_GET_TRANSACTIONS::request req;
COMMAND_RPC_GET_TRANSACTIONS::response res;
req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
@@ -11561,10 +11560,17 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
confirmations = 0;
if (!in_pool)
{
- std::string err;
- uint64_t bc_height = get_daemon_blockchain_height(err);
- if (err.empty())
- confirmations = bc_height - res.txs.front().block_height;
+ if (rpc_version < MAKE_CORE_RPC_VERSION(3, 7))
+ {
+ std::string err;
+ uint64_t bc_height = get_daemon_blockchain_height(err);
+ if (err.empty() && bc_height > res.txs.front().block_height)
+ confirmations = bc_height - res.txs.front().block_height;
+ }
+ else
+ {
+ confirmations = res.txs.front().confirmations;
+ }
}
}
@@ -12027,8 +12033,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
serializable_unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
try
{
- std::istringstream iss(sig_decoded);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(sig_decoded)};
if (::serialization::serialize_noeof(ar, proofs))
if (::serialization::serialize_noeof(ar, subaddr_spendkeys))
if (::serialization::check_stream_state(ar))
@@ -13212,9 +13217,7 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st)
std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> outputs;
try
{
- std::stringstream iss;
- iss << body;
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(body)};
if (::serialization::serialize(ar, outputs))
if (::serialization::check_stream_state(ar))
loaded = true;
@@ -13466,8 +13469,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
bool loaded = false;
try
{
- std::istringstream iss(body);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(body)};
if (::serialization::serialize(ar, i))
if (::serialization::check_stream_state(ar))
loaded = true;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 0b200ae60..b72817ba0 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -762,6 +762,90 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_freeze(const wallet_rpc::COMMAND_RPC_FREEZE::request& req, wallet_rpc::COMMAND_RPC_FREEZE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+ {
+ if (!m_wallet) return not_open(er);
+ try
+ {
+ if (req.key_image.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = std::string("Must specify key image to freeze");
+ return false;
+ }
+ crypto::key_image ki;
+ if (!epee::string_tools::hex_to_pod(req.key_image, ki))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+ er.message = "failed to parse key image";
+ return false;
+ }
+ m_wallet->freeze(ki);
+ }
+ catch (const std::exception& e)
+ {
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+ return false;
+ }
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_thaw(const wallet_rpc::COMMAND_RPC_THAW::request& req, wallet_rpc::COMMAND_RPC_THAW::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+ {
+ if (!m_wallet) return not_open(er);
+ try
+ {
+ if (req.key_image.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = std::string("Must specify key image to thaw");
+ return false;
+ }
+ crypto::key_image ki;
+ if (!epee::string_tools::hex_to_pod(req.key_image, ki))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+ er.message = "failed to parse key image";
+ return false;
+ }
+ m_wallet->thaw(ki);
+ }
+ catch (const std::exception& e)
+ {
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+ return false;
+ }
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_frozen(const wallet_rpc::COMMAND_RPC_FROZEN::request& req, wallet_rpc::COMMAND_RPC_FROZEN::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+ {
+ if (!m_wallet) return not_open(er);
+ try
+ {
+ if (req.key_image.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = std::string("Must specify key image to check if frozen");
+ return false;
+ }
+ crypto::key_image ki;
+ if (!epee::string_tools::hex_to_pod(req.key_image, ki))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+ er.message = "failed to parse key image";
+ return false;
+ }
+ res.frozen = m_wallet->frozen(ki);
+ }
+ catch (const std::exception& e)
+ {
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+ return false;
+ }
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er)
{
crypto::hash8 integrated_payment_id = crypto::null_hash8;
@@ -877,10 +961,10 @@ namespace tools
return amount;
}
//------------------------------------------------------------------------------------------------------------------------------
- template<typename Ts, typename Tu>
+ template<typename Ts, typename Tu, typename Tk>
bool wallet_rpc_server::fill_response(std::vector<tools::wallet2::pending_tx> &ptx_vector,
bool get_tx_key, Ts& tx_key, Tu &amount, Tu &fee, Tu &weight, std::string &multisig_txset, std::string &unsigned_txset, bool do_not_relay,
- Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, epee::json_rpc::error &er)
+ Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, Tk &spent_key_images, epee::json_rpc::error &er)
{
for (const auto & ptx : ptx_vector)
{
@@ -895,6 +979,17 @@ namespace tools
fill(amount, total_amount(ptx));
fill(fee, ptx.fee);
fill(weight, cryptonote::get_transaction_weight(ptx.tx));
+
+ // add spent key images
+ tools::wallet_rpc::key_image_list key_image_list;
+ bool all_are_txin_to_key = std::all_of(ptx.tx.vin.begin(), ptx.tx.vin.end(), [&](const cryptonote::txin_v& s_e) -> bool
+ {
+ CHECKED_GET_SPECIFIC_VARIANT(s_e, const cryptonote::txin_to_key, in, false);
+ key_image_list.key_images.push_back(epee::string_tools::pod_to_hex(in.k_image));
+ return true;
+ });
+ THROW_WALLET_EXCEPTION_IF(!all_are_txin_to_key, error::unexpected_txin_type, ptx.tx);
+ fill(spent_key_images, key_image_list);
}
if (m_wallet->multisig())
@@ -981,7 +1076,7 @@ namespace tools
}
return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.weight, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
- res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
+ res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, res.spent_key_images, er);
}
catch (const std::exception& e)
{
@@ -1027,7 +1122,7 @@ namespace tools
}
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
- res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
+ res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
}
catch (const std::exception& e)
{
@@ -1389,7 +1484,7 @@ namespace tools
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_unmixable_sweep_transactions();
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
- res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
+ res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
}
catch (const std::exception& e)
{
@@ -1447,7 +1542,7 @@ namespace tools
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra, req.account_index, subaddr_indices);
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
- res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
+ res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
}
catch (const std::exception& e)
{
@@ -1522,7 +1617,7 @@ namespace tools
}
return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.weight, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
- res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
+ res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, res.spent_key_images, er);
}
catch (const std::exception& e)
{
@@ -1555,8 +1650,7 @@ namespace tools
try
{
- std::istringstream iss(blob);
- binary_archive<false> ar(iss);
+ binary_archive<false> ar{epee::strspan<std::uint8_t>(blob)};
if (::serialization::serialize(ar, ptx))
loaded = true;
}
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 9f9e3c134..7169c9136 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -84,6 +84,9 @@ namespace tools
MAP_JON_RPC_WE("set_account_tag_description", on_set_account_tag_description, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION)
MAP_JON_RPC_WE("get_height", on_getheight, wallet_rpc::COMMAND_RPC_GET_HEIGHT)
MAP_JON_RPC_WE("getheight", on_getheight, wallet_rpc::COMMAND_RPC_GET_HEIGHT)
+ MAP_JON_RPC_WE("freeze", on_freeze, wallet_rpc::COMMAND_RPC_FREEZE)
+ MAP_JON_RPC_WE("thaw", on_thaw, wallet_rpc::COMMAND_RPC_THAW)
+ MAP_JON_RPC_WE("frozen", on_frozen, wallet_rpc::COMMAND_RPC_FROZEN)
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT)
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER)
@@ -174,6 +177,9 @@ namespace tools
bool on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
+ bool on_freeze(const wallet_rpc::COMMAND_RPC_FREEZE::request& req, wallet_rpc::COMMAND_RPC_FREEZE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
+ bool on_thaw(const wallet_rpc::COMMAND_RPC_THAW::request& req, wallet_rpc::COMMAND_RPC_THAW::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
+ bool on_frozen(const wallet_rpc::COMMAND_RPC_FROZEN::request& req, wallet_rpc::COMMAND_RPC_FROZEN::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_sign_transfer(const wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
@@ -257,10 +263,10 @@ namespace tools
bool not_open(epee::json_rpc::error& er);
void handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code);
- template<typename Ts, typename Tu>
+ template<typename Ts, typename Tu, typename Tk>
bool fill_response(std::vector<tools::wallet2::pending_tx> &ptx_vector,
bool get_tx_key, Ts& tx_key, Tu &amount, Tu &fee, Tu &weight, std::string &multisig_txset, std::string &unsigned_txset, bool do_not_relay,
- Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, epee::json_rpc::error &er);
+ Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, Tk &spent_key_images, epee::json_rpc::error &er);
bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 0002508a2..6640441ed 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 21
+#define WALLET_RPC_VERSION_MINOR 22
#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
@@ -456,6 +456,78 @@ namespace wallet_rpc
END_KV_SERIALIZE_MAP()
};
+ struct COMMAND_RPC_FREEZE
+ {
+ struct request_t
+ {
+ std::string key_image;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(key_image)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<request_t> request;
+
+ struct response_t
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<response_t> response;
+ };
+
+ struct COMMAND_RPC_THAW
+ {
+ struct request_t
+ {
+ std::string key_image;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(key_image)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<request_t> request;
+
+ struct response_t
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<response_t> response;
+ };
+
+ struct COMMAND_RPC_FROZEN
+ {
+ struct request_t
+ {
+ std::string key_image;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(key_image)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<request_t> request;
+
+ struct response_t
+ {
+ bool frozen;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(frozen)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<response_t> response;
+ };
+
+ struct key_image_list
+ {
+ std::list<std::string> key_images;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(key_images)
+ END_KV_SERIALIZE_MAP()
+ };
+
struct COMMAND_RPC_TRANSFER
{
struct request_t
@@ -499,6 +571,7 @@ namespace wallet_rpc
std::string tx_metadata;
std::string multisig_txset;
std::string unsigned_txset;
+ key_image_list spent_key_images;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
@@ -510,6 +583,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_metadata)
KV_SERIALIZE(multisig_txset)
KV_SERIALIZE(unsigned_txset)
+ KV_SERIALIZE(spent_key_images)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -567,6 +641,7 @@ namespace wallet_rpc
std::list<std::string> tx_metadata_list;
std::string multisig_txset;
std::string unsigned_txset;
+ std::list<key_image_list> spent_key_images_list;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
@@ -578,6 +653,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_metadata_list)
KV_SERIALIZE(multisig_txset)
KV_SERIALIZE(unsigned_txset)
+ KV_SERIALIZE(spent_key_images_list)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -742,6 +818,7 @@ namespace wallet_rpc
std::list<std::string> tx_metadata_list;
std::string multisig_txset;
std::string unsigned_txset;
+ std::list<key_image_list> spent_key_images_list;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
@@ -753,6 +830,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_metadata_list)
KV_SERIALIZE(multisig_txset)
KV_SERIALIZE(unsigned_txset)
+ KV_SERIALIZE(spent_key_images_list)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -816,6 +894,7 @@ namespace wallet_rpc
std::list<std::string> tx_metadata_list;
std::string multisig_txset;
std::string unsigned_txset;
+ std::list<key_image_list> spent_key_images_list;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
@@ -827,6 +906,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_metadata_list)
KV_SERIALIZE(multisig_txset)
KV_SERIALIZE(unsigned_txset)
+ KV_SERIALIZE(spent_key_images_list)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -875,6 +955,7 @@ namespace wallet_rpc
std::string tx_metadata;
std::string multisig_txset;
std::string unsigned_txset;
+ key_image_list spent_key_images;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
@@ -886,6 +967,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_metadata)
KV_SERIALIZE(multisig_txset)
KV_SERIALIZE(unsigned_txset)
+ KV_SERIALIZE(spent_key_images)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;