diff --git a/CMakeLists.txt b/CMakeLists.txt index 401a95d75..20571f043 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,6 +169,15 @@ function (monero_set_target_no_relink target) endif() endfunction() +option(STRIP_TARGETS "Strip symbols from targets?" OFF) +function (monero_set_target_strip target) + if (STRIP_TARGETS) + set_target_properties("${target}" PROPERTIES LINK_FLAGS_RELEASE -s) + set_target_properties("${target}" PROPERTIES LINK_FLAGS_DEBUG -s) + # Stripping from Debug might make sense if you're low on disk space, but want to test if debug version builds properly. + endif() +endfunction() + function (monero_add_minimal_executable name) source_group("${name}" FILES @@ -176,7 +185,8 @@ function (monero_add_minimal_executable name) add_executable("${name}" ${ARGN}) - monero_set_target_no_relink( ${name} ) + monero_set_target_no_relink("${name}") + monero_set_target_strip ("${name}") endfunction() # Finds all headers in a directory and its subdirs, to be able to search for them and autosave in IDEs. @@ -579,6 +589,7 @@ function (monero_add_library_with_deps) add_library(${objlib} OBJECT ${MONERO_ADD_LIBRARY_SOURCES}) add_library("${MONERO_ADD_LIBRARY_NAME}" $) monero_set_target_no_relink("${MONERO_ADD_LIBRARY_NAME}") + monero_set_target_strip ("${MONERO_ADD_LIBRARY_NAME}") if (MONERO_ADD_LIBRARY_DEPENDS) add_dependencies(${objlib} ${MONERO_ADD_LIBRARY_DEPENDS}) endif() diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h index 5a6cc0b51..e59cbcf5f 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -28,13 +28,8 @@ #pragma once -#include -#include - -#include "misc_log_ex.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "serialization" +#include +#include namespace epee { @@ -97,46 +92,7 @@ namespace misc_utils return lut[(uint8_t)c] & 1; } - inline std::string transform_to_escape_sequence(const std::string& src) - { - static const char escaped[] = "\b\f\n\r\t\v\"\\/"; - std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)); - if (it == src.end()) - return src; - - std::string res; - res.reserve(2 * src.size()); - res.assign(src.begin(), it); - for(; it!=src.end(); ++it) - { - switch(*it) - { - case '\b': //Backspace (ascii code 08) - res+="\\b"; break; - case '\f': //Form feed (ascii code 0C) - res+="\\f"; break; - case '\n': //New line - res+="\\n"; break; - case '\r': //Carriage return - res+="\\r"; break; - case '\t': //Tab - res+="\\t"; break; - case '\v': //Vertical tab - res+="\\v"; break; - //case '\'': //Apostrophe or single quote - // res+="\\'"; break; - case '"': //Double quote - res+="\\\""; break; - case '\\': //Backslash caracter - res+="\\\\"; break; - case '/': //Backslash caracter - res+="\\/"; break; - default: - res.push_back(*it); - } - } - return res; - } + std::string transform_to_escape_sequence(const std::string& src); /* \b Backspace (ascii code 08) @@ -150,98 +106,7 @@ namespace misc_utils \\ Backslash character */ - inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - bool escape_mode = false; - std::string::const_iterator it = star_end_string; - ++it; - std::string::const_iterator fi = it; - while (fi != buf_end && ((lut[(uint8_t)*fi] & 32)) == 0) - ++fi; - val.assign(it, fi); - it = fi; - for(;it != buf_end;it++) - { - if(escape_mode/*prev_ch == '\\'*/) - { - switch(*it) - { - case 'b': //Backspace (ascii code 08) - val.push_back(0x08);break; - case 'f': //Form feed (ascii code 0C) - val.push_back(0x0C);break; - case 'n': //New line - val.push_back('\n');break; - case 'r': //Carriage return - val.push_back('\r');break; - case 't': //Tab - val.push_back('\t');break; - case 'v': //Vertical tab - val.push_back('\v');break; - case '\'': //Apostrophe or single quote - val.push_back('\'');break; - case '"': //Double quote - val.push_back('"');break; - case '\\': //Backslash character - val.push_back('\\');break; - case '/': //Slash character - val.push_back('/');break; - case 'u': //Unicode code point - if (buf_end - it < 4) - { - ASSERT_MES_AND_THROW("Invalid Unicode escape sequence"); - } - else - { - uint32_t dst = 0; - for (int i = 0; i < 4; ++i) - { - const unsigned char tmp = isx[(unsigned char)*++it]; - CHECK_AND_ASSERT_THROW_MES(tmp != 0xff, "Bad Unicode encoding"); - dst = dst << 4 | tmp; - } - // encode as UTF-8 - if (dst <= 0x7f) - { - val.push_back(dst); - } - else if (dst <= 0x7ff) - { - val.push_back(0xc0 | (dst >> 6)); - val.push_back(0x80 | (dst & 0x3f)); - } - else if (dst <= 0xffff) - { - val.push_back(0xe0 | (dst >> 12)); - val.push_back(0x80 | ((dst >> 6) & 0x3f)); - val.push_back(0x80 | (dst & 0x3f)); - } - else - { - ASSERT_MES_AND_THROW("Unicode code point is out or range"); - } - } - break; - default: - val.push_back(*it); - LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\""); - } - escape_mode = false; - }else if(*it == '"') - { - star_end_string = it; - return; - }else if(*it == '\\') - { - escape_mode = true; - } - else - { - val.push_back(*it); - } - } - ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end)); - } + void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val); inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) { try @@ -255,42 +120,7 @@ namespace misc_utils return false; } } - inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val) - { - val.clear(); - uint8_t float_flag = 0; - is_signed_val = false; - size_t chars = 0; - std::string::const_iterator it = star_end_string; - if (it != buf_end && *it == '-') - { - is_signed_val = true; - ++chars; - ++it; - } - for(;it != buf_end;it++) - { - const uint8_t flags = lut[(uint8_t)*it]; - if (flags & 16) - { - float_flag |= flags; - ++chars; - } - else - { - val = boost::string_ref(&*star_end_string, chars); - if(val.size()) - { - star_end_string = --it; - is_float_val = !!(float_flag & 2); - return; - } - else - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); - } - } - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); - } + void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val); inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { try @@ -304,25 +134,7 @@ namespace misc_utils return false; } } - inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if (!(lut[(uint8_t)*it] & 4)) - { - val = boost::string_ref(&*star_end_string, std::distance(star_end_string, it)); - if(val.size()) - { - star_end_string = --it; - return; - }else - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); - } - } - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); - } + void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val); inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { try @@ -335,44 +147,8 @@ namespace misc_utils return false; } } - inline bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(!isalnum(*it) && *it != '-' && *it != '_') - { - val.assign(star_end_string, it); - if(val.size()) - { - star_end_string = --it; - return true; - }else - return false; - } - } - return false; - } - inline bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end) - { - word_end = star_end_string; - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(isspace(*it)) - { - - continue; - }else if( *it == '=' ) - { - star_end_string = it; - word_end = it; - return true; - } - } - return false; - } + bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val); + bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end); } } } diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index 7bc75caf3..3c5eb49e9 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -31,7 +31,7 @@ set(EPEE_INCLUDE_DIR_BASE "${CMAKE_CURRENT_SOURCE_DIR}/../include") # Add headers to the file list, to be able to search for them and autosave in IDEs. monero_find_all_headers(EPEE_HEADERS_PUBLIC "${EPEE_INCLUDE_DIR_BASE}") -monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp +monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp parserse_base_utils.cpp wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp int-util.cpp portable_storage.cpp misc_language.cpp diff --git a/contrib/epee/src/parserse_base_utils.cpp b/contrib/epee/src/parserse_base_utils.cpp new file mode 100644 index 000000000..112e9c5e4 --- /dev/null +++ b/contrib/epee/src/parserse_base_utils.cpp @@ -0,0 +1,282 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of the Andrey N. Sabelnikov 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 OWNER 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. +// + +#include "storages/parserse_base_utils.h" + +#include "misc_log_ex.h" +#include +#include + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + +namespace epee +{ +namespace misc_utils +{ + namespace parse + { + std::string transform_to_escape_sequence(const std::string& src) + { + static const char escaped[] = "\b\f\n\r\t\v\"\\/"; + std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)); + if (it == src.end()) + return src; + + std::string res; + res.reserve(2 * src.size()); + res.assign(src.begin(), it); + for(; it!=src.end(); ++it) + { + switch(*it) + { + case '\b': //Backspace (ascii code 08) + res+="\\b"; break; + case '\f': //Form feed (ascii code 0C) + res+="\\f"; break; + case '\n': //New line + res+="\\n"; break; + case '\r': //Carriage return + res+="\\r"; break; + case '\t': //Tab + res+="\\t"; break; + case '\v': //Vertical tab + res+="\\v"; break; + //case '\'': //Apostrophe or single quote + // res+="\\'"; break; + case '"': //Double quote + res+="\\\""; break; + case '\\': //Backslash caracter + res+="\\\\"; break; + case '/': //Backslash caracter + res+="\\/"; break; + default: + res.push_back(*it); + } + } + return res; + } + /* + + \b Backspace (ascii code 08) + \f Form feed (ascii code 0C) + \n New line + \r Carriage return + \t Tab + \v Vertical tab + \' Apostrophe or single quote + \" Double quote + \\ Backslash character + + */ + void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + bool escape_mode = false; + std::string::const_iterator it = star_end_string; + ++it; + std::string::const_iterator fi = it; + while (fi != buf_end && ((lut[(uint8_t)*fi] & 32)) == 0) + ++fi; + val.assign(it, fi); + it = fi; + for(;it != buf_end;it++) + { + if(escape_mode/*prev_ch == '\\'*/) + { + switch(*it) + { + case 'b': //Backspace (ascii code 08) + val.push_back(0x08);break; + case 'f': //Form feed (ascii code 0C) + val.push_back(0x0C);break; + case 'n': //New line + val.push_back('\n');break; + case 'r': //Carriage return + val.push_back('\r');break; + case 't': //Tab + val.push_back('\t');break; + case 'v': //Vertical tab + val.push_back('\v');break; + case '\'': //Apostrophe or single quote + val.push_back('\'');break; + case '"': //Double quote + val.push_back('"');break; + case '\\': //Backslash character + val.push_back('\\');break; + case '/': //Slash character + val.push_back('/');break; + case 'u': //Unicode code point + if (buf_end - it < 4) + { + ASSERT_MES_AND_THROW("Invalid Unicode escape sequence"); + } + else + { + uint32_t dst = 0; + for (int i = 0; i < 4; ++i) + { + const unsigned char tmp = isx[(unsigned char)*++it]; + CHECK_AND_ASSERT_THROW_MES(tmp != 0xff, "Bad Unicode encoding"); + dst = dst << 4 | tmp; + } + // encode as UTF-8 + if (dst <= 0x7f) + { + val.push_back(dst); + } + else if (dst <= 0x7ff) + { + val.push_back(0xc0 | (dst >> 6)); + val.push_back(0x80 | (dst & 0x3f)); + } + else if (dst <= 0xffff) + { + val.push_back(0xe0 | (dst >> 12)); + val.push_back(0x80 | ((dst >> 6) & 0x3f)); + val.push_back(0x80 | (dst & 0x3f)); + } + else + { + ASSERT_MES_AND_THROW("Unicode code point is out or range"); + } + } + break; + default: + val.push_back(*it); + LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\""); + } + escape_mode = false; + }else if(*it == '"') + { + star_end_string = it; + return; + }else if(*it == '\\') + { + escape_mode = true; + } + else + { + val.push_back(*it); + } + } + ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end)); + } + void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val) + { + val.clear(); + uint8_t float_flag = 0; + is_signed_val = false; + size_t chars = 0; + std::string::const_iterator it = star_end_string; + if (it != buf_end && *it == '-') + { + is_signed_val = true; + ++chars; + ++it; + } + for(;it != buf_end;it++) + { + const uint8_t flags = lut[(uint8_t)*it]; + if (flags & 16) + { + float_flag |= flags; + ++chars; + } + else + { + val = boost::string_ref(&*star_end_string, chars); + if(val.size()) + { + star_end_string = --it; + is_float_val = !!(float_flag & 2); + return; + } + else + ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); + } + } + ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); + } + void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) + { + val.clear(); + + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if (!(lut[(uint8_t)*it] & 4)) + { + val = boost::string_ref(&*star_end_string, std::distance(star_end_string, it)); + if(val.size()) + { + star_end_string = --it; + return; + }else + ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); + } + } + ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); + } + bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + val.clear(); + + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if(!isalnum(*it) && *it != '-' && *it != '_') + { + val.assign(star_end_string, it); + if(val.size()) + { + star_end_string = --it; + return true; + }else + return false; + } + } + return false; + } + bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end) + { + word_end = star_end_string; + + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if(isspace(*it)) + { + + continue; + }else if( *it == '=' ) + { + star_end_string = it; + word_end = it; + return true; + } + } + return false; + } + } +} +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a440ddf4..c6d21975d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,7 @@ function (monero_add_executable name) enable_stack_trace("${name}") monero_set_target_no_relink("${name}") + monero_set_target_strip ("${name}") endfunction () include(Version) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 4bde67fe3..ebcca9289 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -961,10 +961,10 @@ namespace tools return amount; } //------------------------------------------------------------------------------------------------------------------------------ - template + template bool wallet_rpc_server::fill_response(std::vector &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) { @@ -979,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()) @@ -1065,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) { @@ -1111,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) { @@ -1473,7 +1484,7 @@ namespace tools std::vector 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) { @@ -1531,7 +1542,7 @@ namespace tools std::vector 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) { @@ -1606,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) { diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index e1f27ea40..7169c9136 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -263,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 + template bool fill_response(std::vector &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& destinations, const std::string& payment_id, std::vector& dsts, std::vector& 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 07cda2ba7..6640441ed 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -519,6 +519,15 @@ namespace wallet_rpc typedef epee::misc_utils::struct_init response; }; + struct key_image_list + { + std::list key_images; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(key_images) + END_KV_SERIALIZE_MAP() + }; + struct COMMAND_RPC_TRANSFER { struct request_t @@ -562,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) @@ -573,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; @@ -630,6 +641,7 @@ namespace wallet_rpc std::list tx_metadata_list; std::string multisig_txset; std::string unsigned_txset; + std::list spent_key_images_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) @@ -641,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; @@ -805,6 +818,7 @@ namespace wallet_rpc std::list tx_metadata_list; std::string multisig_txset; std::string unsigned_txset; + std::list spent_key_images_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) @@ -816,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; @@ -879,6 +894,7 @@ namespace wallet_rpc std::list tx_metadata_list; std::string multisig_txset; std::string unsigned_txset; + std::list spent_key_images_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) @@ -890,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; @@ -938,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) @@ -949,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; diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py index aca7c82bb..02084620c 100644 --- a/utils/python-rpc/framework/wallet.py +++ b/utils/python-rpc/framework/wallet.py @@ -1099,3 +1099,36 @@ class Wallet(object): 'id': '0' } return self.rpc.send_json_rpc_request(scan_tx) + + def freeze(self, key_image): + freeze = { + 'method': 'freeze', + 'jsonrpc': '2.0', + 'params' : { + 'key_image': key_image, + }, + 'id': '0' + } + return self.rpc.send_json_rpc_request(freeze) + + def thaw(self, key_image): + thaw = { + 'method': 'thaw', + 'jsonrpc': '2.0', + 'params' : { + 'key_image': key_image, + }, + 'id': '0' + } + return self.rpc.send_json_rpc_request(thaw) + + def frozen(self, key_image): + frozen = { + 'method': 'frozen', + 'jsonrpc': '2.0', + 'params' : { + 'key_image': key_image, + }, + 'id': '0' + } + return self.rpc.send_json_rpc_request(frozen)