aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/wallet.cpp3
-rw-r--r--src/wallet/message_transporter.cpp2
-rw-r--r--src/wallet/wallet2.cpp87
-rw-r--r--src/wallet/wallet_rpc_server.h1
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h140
5 files changed, 144 insertions, 89 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 0c3aaf853..7f4dbbc79 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -45,7 +45,10 @@
#include <sstream>
#include <unordered_map>
+#ifdef WIN32
#include <boost/locale.hpp>
+#endif
+
#include <boost/filesystem.hpp>
using namespace std;
diff --git a/src/wallet/message_transporter.cpp b/src/wallet/message_transporter.cpp
index 7aa765c87..b4f6ce7bd 100644
--- a/src/wallet/message_transporter.cpp
+++ b/src/wallet/message_transporter.cpp
@@ -61,7 +61,7 @@ namespace bitmessage_rpc
KV_SERIALIZE(toAddress)
KV_SERIALIZE(read)
KV_SERIALIZE(msgid)
- KV_SERIALIZE(message);
+ KV_SERIALIZE(message)
KV_SERIALIZE(fromAddress)
KV_SERIALIZE(receivedTime)
KV_SERIALIZE(subject)
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index ddca6256d..12e4621bf 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -3317,7 +3317,7 @@ void check_block_hard_fork_version(cryptonote::network_type nettype, uint8_t hf_
if (wallet_hard_forks[fork_index].version == hf_version)
break;
THROW_WALLET_EXCEPTION_IF(fork_index == wallet_num_hard_forks, error::wallet_internal_error, "Fork not found in table");
- uint64_t start_height = wallet_hard_forks[fork_index].height;
+ uint64_t start_height = hf_version == 1 ? 0 : wallet_hard_forks[fork_index].height;
uint64_t end_height = fork_index == wallet_num_hard_forks - 1
? std::numeric_limits<uint64_t>::max()
: wallet_hard_forks[fork_index + 1].height;
@@ -6163,6 +6163,20 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file);
}
+ // Wallets used to wipe, but not erase, old unused multisig key info, which lead to huge memory leaks.
+ // Here we erase these multisig keys if they're zero'd out to free up space.
+ for (auto &td : m_transfers)
+ {
+ auto mk_it = td.m_multisig_k.begin();
+ while (mk_it != td.m_multisig_k.end())
+ {
+ if (*mk_it == rct::zero())
+ mk_it = td.m_multisig_k.erase(mk_it);
+ else
+ ++mk_it;
+ }
+ }
+
cryptonote::block genesis;
generate_genesis(genesis);
crypto::hash genesis_hash = get_block_hash(genesis);
@@ -7036,7 +7050,10 @@ void wallet2::commit_tx(pending_tx& ptx)
// tx generated, get rid of used k values
for (size_t idx: ptx.selected_transfers)
+ {
memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
+ m_transfers[idx].m_multisig_k.clear();
+ }
//fee includes dust if dust policy specified it.
LOG_PRINT_L1("Transaction successfully sent. <" << txid << ">" << ENDL
@@ -7538,7 +7555,10 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs)
// txes generated, get rid of used k values
for (size_t n = 0; n < txs.m_ptx.size(); ++n)
for (size_t idx: txs.m_ptx[n].construction_data.selected_transfers)
+ {
memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
+ m_transfers[idx].m_multisig_k.clear();
+ }
// zero out some data we don't want to share
for (auto &ptx: txs.m_ptx)
@@ -7862,7 +7882,10 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
// inputs in the transactions worked on here)
for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n)
for (size_t idx: exported_txs.m_ptx[n].construction_data.selected_transfers)
+ {
memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
+ m_transfers[idx].m_multisig_k.clear();
+ }
exported_txs.m_signers.insert(get_multisig_signer_public_key());
@@ -8660,6 +8683,26 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
COMMAND_RPC_GET_OUTPUTS_BIN::request req = AUTO_VAL_INIT(req);
COMMAND_RPC_GET_OUTPUTS_BIN::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
+ // The secret picking order contains outputs in the order that we selected them.
+ //
+ // We will later sort the output request entries in a pre-determined order so that the daemon
+ // that we're requesting information from doesn't learn any information about the true spend
+ // for each ring. However, internally, we want to prefer to construct our rings using the
+ // outputs that we picked first versus outputs picked later.
+ //
+ // The reason why is because each consecutive output pick within a ring becomes increasing less
+ // statistically independent from other picks, since we pick outputs from a finite set
+ // *without replacement*, due to the protocol not allowing duplicate ring members. This effect
+ // is exacerbated by the fact that we pick 1.5x + 75 as many outputs as we need per RPC
+ // request to account for unusable outputs. This effect is small, but non-neglibile and gets
+ // worse with larger ring sizes.
+ std::vector<get_outputs_out> secret_picking_order;
+
+ // Convenience/safety lambda to make sure that both output lists req.outputs and secret_picking_order are updated together
+ // Each ring section of req.outputs gets sorted later after selecting all outputs for that ring
+ const auto add_output_to_lists = [&req, &secret_picking_order](const get_outputs_out &goo)
+ { req.outputs.push_back(goo); secret_picking_order.push_back(goo); };
+
std::unique_ptr<gamma_picker> gamma;
if (has_rct)
gamma.reset(new gamma_picker(rct_offsets));
@@ -8794,7 +8837,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
if (out < num_outs)
{
MINFO("Using it");
- req.outputs.push_back({amount, out});
+ add_output_to_lists({amount, out});
++num_found;
seen_indices.emplace(out);
if (out == td.m_global_output_index)
@@ -8816,12 +8859,12 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
if (num_outs <= requested_outputs_count)
{
for (uint64_t i = 0; i < num_outs; i++)
- req.outputs.push_back({amount, i});
+ add_output_to_lists({amount, i});
// duplicate to make up shortfall: this will be caught after the RPC call,
// so we can also output the amounts for which we can't reach the required
// mixin after checking the actual unlockedness
for (uint64_t i = num_outs; i < requested_outputs_count; ++i)
- req.outputs.push_back({amount, num_outs - 1});
+ add_output_to_lists({amount, num_outs - 1});
}
else
{
@@ -8830,7 +8873,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
{
num_found = 1;
seen_indices.emplace(td.m_global_output_index);
- req.outputs.push_back({amount, td.m_global_output_index});
+ add_output_to_lists({amount, td.m_global_output_index});
LOG_PRINT_L1("Selecting real output: " << td.m_global_output_index << " for " << print_money(amount));
}
@@ -8938,7 +8981,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
seen_indices.emplace(i);
picks[type].insert(i);
- req.outputs.push_back({amount, i});
+ add_output_to_lists({amount, i});
++num_found;
MDEBUG("picked " << i << ", " << num_found << " now picked");
}
@@ -8952,7 +8995,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
// we'll error out later
while (num_found < requested_outputs_count)
{
- req.outputs.push_back({amount, 0});
+ add_output_to_lists({amount, 0});
++num_found;
}
}
@@ -8962,6 +9005,10 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
[](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; });
}
+ THROW_WALLET_EXCEPTION_IF(req.outputs.size() != secret_picking_order.size(), error::wallet_internal_error,
+ "bug: we did not update req.outputs/secret_picking_order in tandem");
+
+ // List all requested outputs to debug log
if (ELPP->vRegistry()->allowed(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY))
{
std::map<uint64_t, std::set<uint64_t>> outs;
@@ -9079,18 +9126,21 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
}
}
- // then pick others in random order till we reach the required number
- // since we use an equiprobable pick here, we don't upset the triangular distribution
- std::vector<size_t> order;
- order.resize(requested_outputs_count);
- for (size_t n = 0; n < order.size(); ++n)
- order[n] = n;
- std::shuffle(order.begin(), order.end(), crypto::random_device{});
-
+ // While we are still lacking outputs in this result ring, in our secret pick order...
LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs of size " << print_money(td.is_rct() ? 0 : td.amount()));
- for (size_t o = 0; o < requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++o)
+ for (size_t ring_pick_idx = base; ring_pick_idx < base + requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++ring_pick_idx)
{
- size_t i = base + order[o];
+ const get_outputs_out attempted_output = secret_picking_order[ring_pick_idx];
+
+ // Find the index i of our pick in the request/response arrays
+ size_t i;
+ for (i = base; i < base + requested_outputs_count; ++i)
+ if (req.outputs[i].index == attempted_output.index)
+ break;
+ THROW_WALLET_EXCEPTION_IF(i == base + requested_outputs_count, error::wallet_internal_error,
+ "Could not find index of picked output in requested outputs");
+
+ // Try adding this output's information to result ring if output isn't invalid
LOG_PRINT_L2("Index " << i << "/" << requested_outputs_count << ": idx " << req.outputs[i].index << " (real " << td.m_global_output_index << "), unlocked " << daemon_resp.outs[i].unlocked << ", key " << daemon_resp.outs[i].key);
tx_add_fake_output(outs, req.outputs[i].index, daemon_resp.outs[i].key, daemon_resp.outs[i].mask, td.m_global_output_index, daemon_resp.outs[i].unlocked, valid_public_keys_cache);
}
@@ -13509,7 +13559,10 @@ cryptonote::blobdata wallet2::export_multisig()
transfer_details &td = m_transfers[n];
crypto::key_image ki;
if (td.m_multisig_k.size())
+ {
memwipe(td.m_multisig_k.data(), td.m_multisig_k.size() * sizeof(td.m_multisig_k[0]));
+ td.m_multisig_k.clear();
+ }
info[n].m_LR.clear();
info[n].m_partial_key_images.clear();
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 282035052..97fc0a278 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -35,7 +35,6 @@
#include <string>
#include "common/util.h"
#include "net/http_server_impl_base.h"
-#include "math_helper.h"
#include "wallet_rpc_server_commands_defs.h"
#include "wallet2.h"
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index c00271030..33afefb80 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -68,8 +68,8 @@ namespace wallet_rpc
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(account_index)
KV_SERIALIZE(address_indices)
- KV_SERIALIZE_OPT(all_accounts, false);
- KV_SERIALIZE_OPT(strict, false);
+ KV_SERIALIZE_OPT(all_accounts, false)
+ KV_SERIALIZE_OPT(strict, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -348,9 +348,9 @@ namespace wallet_rpc
std::vector<uint32_t> accounts;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(tag);
- KV_SERIALIZE(label);
- KV_SERIALIZE(accounts);
+ KV_SERIALIZE(tag)
+ KV_SERIALIZE(label)
+ KV_SERIALIZE(accounts)
END_KV_SERIALIZE_MAP()
};
@@ -1029,7 +1029,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_hash)
KV_SERIALIZE(subaddr_index)
KV_SERIALIZE(key_image)
- KV_SERIALIZE(pubkey);
+ KV_SERIALIZE(pubkey)
KV_SERIALIZE(block_height)
KV_SERIALIZE(frozen)
KV_SERIALIZE(unlocked)
@@ -1165,7 +1165,7 @@ namespace wallet_rpc
bool hard;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_OPT(hard, false);
+ KV_SERIALIZE_OPT(hard, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1408,21 +1408,21 @@ namespace wallet_rpc
uint64_t suggested_confirmations_threshold;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(txid);
- KV_SERIALIZE(payment_id);
- KV_SERIALIZE(height);
- KV_SERIALIZE(timestamp);
- KV_SERIALIZE(amount);
- KV_SERIALIZE(amounts);
- KV_SERIALIZE(fee);
- KV_SERIALIZE(note);
- KV_SERIALIZE(destinations);
- KV_SERIALIZE(type);
+ KV_SERIALIZE(txid)
+ KV_SERIALIZE(payment_id)
+ KV_SERIALIZE(height)
+ KV_SERIALIZE(timestamp)
+ KV_SERIALIZE(amount)
+ KV_SERIALIZE(amounts)
+ KV_SERIALIZE(fee)
+ KV_SERIALIZE(note)
+ KV_SERIALIZE(destinations)
+ KV_SERIALIZE(type)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(locked)
- KV_SERIALIZE(subaddr_index);
- KV_SERIALIZE(subaddr_indices);
- KV_SERIALIZE(address);
+ KV_SERIALIZE(subaddr_index)
+ KV_SERIALIZE(subaddr_indices)
+ KV_SERIALIZE(address)
KV_SERIALIZE(double_spend_seen)
KV_SERIALIZE_OPT(confirmations, (uint64_t)0)
KV_SERIALIZE_OPT(suggested_confirmations_threshold, (uint64_t)0)
@@ -1559,17 +1559,17 @@ namespace wallet_rpc
bool all_accounts;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(in);
- KV_SERIALIZE(out);
- KV_SERIALIZE(pending);
- KV_SERIALIZE(failed);
- KV_SERIALIZE(pool);
- KV_SERIALIZE(filter_by_height);
- KV_SERIALIZE(min_height);
- KV_SERIALIZE_OPT(max_height, (uint64_t)CRYPTONOTE_MAX_BLOCK_NUMBER);
- KV_SERIALIZE(account_index);
- KV_SERIALIZE(subaddr_indices);
- KV_SERIALIZE_OPT(all_accounts, false);
+ KV_SERIALIZE(in)
+ KV_SERIALIZE(out)
+ KV_SERIALIZE(pending)
+ KV_SERIALIZE(failed)
+ KV_SERIALIZE(pool)
+ KV_SERIALIZE(filter_by_height)
+ KV_SERIALIZE(min_height)
+ KV_SERIALIZE_OPT(max_height, (uint64_t)CRYPTONOTE_MAX_BLOCK_NUMBER)
+ KV_SERIALIZE(account_index)
+ KV_SERIALIZE(subaddr_indices)
+ KV_SERIALIZE_OPT(all_accounts, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1583,11 +1583,11 @@ namespace wallet_rpc
std::list<transfer_entry> pool;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(in);
- KV_SERIALIZE(out);
- KV_SERIALIZE(pending);
- KV_SERIALIZE(failed);
- KV_SERIALIZE(pool);
+ KV_SERIALIZE(in)
+ KV_SERIALIZE(out)
+ KV_SERIALIZE(pending)
+ KV_SERIALIZE(failed)
+ KV_SERIALIZE(pool)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1601,7 +1601,7 @@ namespace wallet_rpc
uint32_t account_index;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(txid);
+ KV_SERIALIZE(txid)
KV_SERIALIZE_OPT(account_index, (uint32_t)0)
END_KV_SERIALIZE_MAP()
};
@@ -1613,8 +1613,8 @@ namespace wallet_rpc
std::list<transfer_entry> transfers;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(transfer);
- KV_SERIALIZE(transfers);
+ KV_SERIALIZE(transfer)
+ KV_SERIALIZE(transfers)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1643,7 +1643,7 @@ namespace wallet_rpc
std::string signature;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(signature);
+ KV_SERIALIZE(signature)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1658,9 +1658,9 @@ namespace wallet_rpc
std::string signature;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(data);
- KV_SERIALIZE(address);
- KV_SERIALIZE(signature);
+ KV_SERIALIZE(data)
+ KV_SERIALIZE(address)
+ KV_SERIALIZE(signature)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1673,10 +1673,10 @@ namespace wallet_rpc
std::string signature_type;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(good);
- KV_SERIALIZE(version);
- KV_SERIALIZE(old);
- KV_SERIALIZE(signature_type);
+ KV_SERIALIZE(good)
+ KV_SERIALIZE(version)
+ KV_SERIALIZE(old)
+ KV_SERIALIZE(signature_type)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1703,7 +1703,7 @@ namespace wallet_rpc
std::string outputs_data_hex;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(outputs_data_hex);
+ KV_SERIALIZE(outputs_data_hex)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1716,7 +1716,7 @@ namespace wallet_rpc
std::string outputs_data_hex;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(outputs_data_hex);
+ KV_SERIALIZE(outputs_data_hex)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1726,7 +1726,7 @@ namespace wallet_rpc
uint64_t num_imported;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(num_imported);
+ KV_SERIALIZE(num_imported)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1739,7 +1739,7 @@ namespace wallet_rpc
bool all;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_OPT(all, false);
+ KV_SERIALIZE_OPT(all, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1750,8 +1750,8 @@ namespace wallet_rpc
std::string signature;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(key_image);
- KV_SERIALIZE(signature);
+ KV_SERIALIZE(key_image)
+ KV_SERIALIZE(signature)
END_KV_SERIALIZE_MAP()
};
@@ -1761,8 +1761,8 @@ namespace wallet_rpc
std::vector<signed_key_image> signed_key_images;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(offset);
- KV_SERIALIZE(signed_key_images);
+ KV_SERIALIZE(offset)
+ KV_SERIALIZE(signed_key_images)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1776,8 +1776,8 @@ namespace wallet_rpc
std::string signature;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(key_image);
- KV_SERIALIZE(signature);
+ KV_SERIALIZE(key_image)
+ KV_SERIALIZE(signature)
END_KV_SERIALIZE_MAP()
};
@@ -1787,8 +1787,8 @@ namespace wallet_rpc
std::vector<signed_key_image> signed_key_images;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_OPT(offset, (uint32_t)0);
- KV_SERIALIZE(signed_key_images);
+ KV_SERIALIZE_OPT(offset, (uint32_t)0)
+ KV_SERIALIZE(signed_key_images)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1817,11 +1817,11 @@ namespace wallet_rpc
std::string recipient_name;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(address);
- KV_SERIALIZE(payment_id);
- KV_SERIALIZE(amount);
- KV_SERIALIZE(tx_description);
- KV_SERIALIZE(recipient_name);
+ KV_SERIALIZE(address)
+ KV_SERIALIZE(payment_id)
+ KV_SERIALIZE(amount)
+ KV_SERIALIZE(tx_description)
+ KV_SERIALIZE(recipient_name)
END_KV_SERIALIZE_MAP()
};
@@ -1861,8 +1861,8 @@ namespace wallet_rpc
std::vector<std::string> unknown_parameters;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(uri);
- KV_SERIALIZE(unknown_parameters);
+ KV_SERIALIZE(uri)
+ KV_SERIALIZE(unknown_parameters)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1887,7 +1887,7 @@ namespace wallet_rpc
uint64_t index;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(index);
+ KV_SERIALIZE(index)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1964,7 +1964,7 @@ namespace wallet_rpc
uint64_t index;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(index);
+ KV_SERIALIZE(index)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2012,8 +2012,8 @@ namespace wallet_rpc
bool received_money;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(blocks_fetched);
- KV_SERIALIZE(received_money);
+ KV_SERIALIZE(blocks_fetched)
+ KV_SERIALIZE(received_money)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;