From 418adb785790a42c1ecfb9ba0e29cf67bfb67c92 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Wed, 17 Jul 2024 20:09:55 -0600
Subject: [PATCH 01/12] add endpoints: export_encrypted_key_images and
 import_encrypted_key_images

---
 src/wallet/wallet_rpc_server.cpp             |   96 +
 src/wallet/wallet_rpc_server.h               |    6 +-
 src/wallet/wallet_rpc_server_commands_defs.h | 5215 +++++++++---------
 3 files changed, 2735 insertions(+), 2582 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 376c58f89..7de53371c 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -2952,6 +2952,102 @@ namespace tools
     return true;
   }
   //------------------------------------------------------------------------------------------------------------------------------
+  bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+  {
+    if (!m_wallet) return not_open(er);
+    try
+    {
+      std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
+      res.offset = ski.first;
+
+      // Serialize the key images and signatures into a single blob
+      std::string data;
+      data.reserve(ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)));
+      for (const auto &item : ski.second)
+      {
+	data += std::string((const char *)&item.first, sizeof(crypto::key_image));
+	data += std::string((const char *)&item.second, sizeof(crypto::signature));
+      }
+
+      // Encrypt the serialized data
+      std::string ciphertext = m_wallet->encrypt_with_view_secret_key(data);
+
+      // Encode the encrypted data as hex
+      res.encrypted_key_images_blob = epee::string_tools::buff_to_hex_nodelimer(ciphertext);
+    }
+    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_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+  {
+    if (!m_wallet) return not_open(er);
+    if (m_restricted)
+    {
+      er.code = WALLET_RPC_ERROR_CODE_DENIED;
+      er.message = "Command unavailable in restricted mode.";
+      return false;
+    }
+    if (!m_wallet->is_trusted_daemon())
+    {
+      er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+      er.message = "This command requires a trusted daemon.";
+      return false;
+    }
+    try
+    {
+      // Decode the hex-encoded encrypted blob
+      std::string ciphertext;
+      if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, ciphertext))
+      {
+	er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+	er.message = "Failed to parse encrypted key images blob";
+	return false;
+      }
+
+      // Decrypt the ciphertext
+      std::string decrypted_data = m_wallet->decrypt_with_view_secret_key(ciphertext);
+
+      // Deserialize the decrypted data into key images and signatures
+      std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
+      const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
+      if (decrypted_data.size() % record_size != 0)
+      {
+	er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+	er.message = "Decrypted data size is not a multiple of the record size";
+	return false;
+      }
+      size_t num_records = decrypted_data.size() / record_size;
+      ski.reserve(num_records);
+      for (size_t i = 0; i < num_records; ++i)
+      {
+	crypto::key_image ki;
+	crypto::signature sig;
+	memcpy(&ki, &decrypted_data[i * record_size], sizeof(crypto::key_image));
+	memcpy(&sig, &decrypted_data[i * record_size + sizeof(crypto::key_image)], sizeof(crypto::signature));
+	ski.emplace_back(ki, sig);
+      }
+
+      uint64_t spent = 0, unspent = 0;
+      uint64_t height = m_wallet->import_key_images(ski, req.offset, spent, unspent);
+      res.height = height;
+      res.spent = spent;
+      res.unspent = unspent;
+    }
+    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_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er, const connection_context *ctx)
   {
     if (!m_wallet) return not_open(er);
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index bfb7013e2..246fe7c27 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -124,7 +124,9 @@ namespace tools
         MAP_JON_RPC_WE("export_outputs",     on_export_outputs,     wallet_rpc::COMMAND_RPC_EXPORT_OUTPUTS)
         MAP_JON_RPC_WE("import_outputs",     on_import_outputs,     wallet_rpc::COMMAND_RPC_IMPORT_OUTPUTS)
         MAP_JON_RPC_WE("export_key_images",  on_export_key_images,  wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES)
-        MAP_JON_RPC_WE("import_key_images",  on_import_key_images,  wallet_rpc::COMMAND_RPC_IMPORT_KEY_IMAGES)
+	MAP_JON_RPC_WE("import_key_images",  on_import_key_images,  wallet_rpc::COMMAND_RPC_IMPORT_KEY_IMAGES)
+	MAP_JON_RPC_WE("export_encrypted_key_images",  on_export_encrypted_key_images,  wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES)
+	MAP_JON_RPC_WE("import_encrypted_key_images",  on_import_encrypted_key_images,  wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES)
         MAP_JON_RPC_WE("make_uri",           on_make_uri,           wallet_rpc::COMMAND_RPC_MAKE_URI)
         MAP_JON_RPC_WE("parse_uri",          on_parse_uri,          wallet_rpc::COMMAND_RPC_PARSE_URI)
         MAP_JON_RPC_WE("get_address_book",   on_get_address_book,   wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY)
@@ -216,6 +218,8 @@ namespace tools
       bool on_import_outputs(const wallet_rpc::COMMAND_RPC_IMPORT_OUTPUTS::request& req, wallet_rpc::COMMAND_RPC_IMPORT_OUTPUTS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
       bool on_export_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
       bool on_import_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
+      bool on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
+      bool on_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
       bool on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
       bool on_parse_uri(const wallet_rpc::COMMAND_RPC_PARSE_URI::request& req, wallet_rpc::COMMAND_RPC_PARSE_URI::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
       bool on_get_address_book(const wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 2173f5b6e..42b43a26b 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -52,2653 +52,2706 @@
 #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
 namespace tools
 {
-namespace wallet_rpc
-{
+  namespace wallet_rpc
+  {
 #define WALLET_RPC_STATUS_OK      "OK"
 #define WALLET_RPC_STATUS_BUSY    "BUSY"
 
-  struct COMMAND_RPC_GET_BALANCE
-  {
-    struct request_t
-    {
-      uint32_t account_index;
-      std::set<uint32_t> address_indices;
-      bool all_accounts;
-      bool strict;
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(address_indices)
-        KV_SERIALIZE_OPT(all_accounts, false)
-        KV_SERIALIZE_OPT(strict, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct per_subaddress_info
-    {
-      uint32_t account_index;
-      uint32_t address_index;
-      std::string address;
-      uint64_t balance;
-      uint64_t unlocked_balance;
-      std::string label;
-      uint64_t num_unspent_outputs;
-      uint64_t blocks_to_unlock;
-      uint64_t time_to_unlock;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(address_index)
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(balance)
-        KV_SERIALIZE(unlocked_balance)
-        KV_SERIALIZE(label)
-        KV_SERIALIZE(num_unspent_outputs)
-        KV_SERIALIZE(blocks_to_unlock)
-        KV_SERIALIZE(time_to_unlock)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response_t
-    {
-      uint64_t 	 balance;
-      uint64_t 	 unlocked_balance;
-      bool       multisig_import_needed;
-      std::vector<per_subaddress_info> per_subaddress;
-      uint64_t   blocks_to_unlock;
-      uint64_t   time_to_unlock;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(balance)
-        KV_SERIALIZE(unlocked_balance)
-        KV_SERIALIZE(multisig_import_needed)
-        KV_SERIALIZE(per_subaddress)
-        KV_SERIALIZE(blocks_to_unlock)
-        KV_SERIALIZE(time_to_unlock)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-    struct COMMAND_RPC_GET_ADDRESS
-  {
-    struct request_t
-    {
-      uint32_t account_index;
-      std::vector<uint32_t> address_index;
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(address_index)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct address_info
-    {
-      std::string address;
-      std::string label;
-      uint32_t address_index;
-      bool used;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(label)
-        KV_SERIALIZE(address_index)
-        KV_SERIALIZE(used)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response_t
-    {
-      std::string address;                  // to remain compatible with older RPC format
-      std::vector<address_info> addresses;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(addresses)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_ADDRESS_INDEX
-  {
-    struct request_t
-    {
-      std::string address;
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      cryptonote::subaddress_index index;
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(index)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CREATE_ADDRESS
-  {
-    struct request_t
-    {
-      uint32_t    account_index;
-      uint32_t    count;
-      std::string label;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE_OPT(count, 1U)
-        KV_SERIALIZE(label)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string              address;
-      uint32_t                 address_index;
-      std::vector<std::string> addresses;
-      std::vector<uint32_t>    address_indices;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(address_index)
-        KV_SERIALIZE(addresses)
-        KV_SERIALIZE(address_indices)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_LABEL_ADDRESS
-  {
-    struct request_t
-    {
-      cryptonote::subaddress_index index;
-      std::string label;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(index)
-        KV_SERIALIZE(label)
-      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_GET_ACCOUNTS
-  {
-    struct request_t
-    {
-      std::string tag;      // all accounts if empty, otherwise those accounts with this tag
-      bool strict_balances;
-      bool regexp; // allow regular expression filters if set to true
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tag)
-        KV_SERIALIZE_OPT(strict_balances, false)
-        KV_SERIALIZE_OPT(regexp, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct subaddress_account_info
-    {
-      uint32_t account_index;
-      std::string base_address;
-      uint64_t balance;
-      uint64_t unlocked_balance;
-      std::string label;
-      std::string tag;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(base_address)
-        KV_SERIALIZE(balance)
-        KV_SERIALIZE(unlocked_balance)
-        KV_SERIALIZE(label)
-        KV_SERIALIZE(tag)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response_t
-    {
-      uint64_t total_balance;
-      uint64_t total_unlocked_balance;
-      std::vector<subaddress_account_info> subaddress_accounts;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(total_balance)
-        KV_SERIALIZE(total_unlocked_balance)
-        KV_SERIALIZE(subaddress_accounts)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CREATE_ACCOUNT
-  {
-    struct request_t
-    {
-      std::string label;
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(label)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint32_t account_index;
-      std::string address;      // the 0-th address for convenience
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(address)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_LABEL_ACCOUNT
-  {
-    struct request_t
-    {
-      uint32_t account_index;
-      std::string label;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(label)
-      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_GET_ACCOUNT_TAGS
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct account_tag_info
-    {
-      std::string tag;
-      std::string label;
-      std::vector<uint32_t> accounts;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tag)
-        KV_SERIALIZE(label)
-        KV_SERIALIZE(accounts)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response_t
-    {
-      std::vector<account_tag_info> account_tags;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(account_tags)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_TAG_ACCOUNTS
-  {
-    struct request_t
-    {
-      std::string tag;
-      std::set<uint32_t> accounts;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tag)
-        KV_SERIALIZE(accounts)
-      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_UNTAG_ACCOUNTS
-  {
-    struct request_t
-    {
-      std::set<uint32_t> accounts;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(accounts)
-      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_SET_ACCOUNT_TAG_DESCRIPTION
-  {
-    struct request_t
-    {
-      std::string tag;
-      std::string description;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tag)
-        KV_SERIALIZE(description)
-      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_GET_HEIGHT
+    struct COMMAND_RPC_GET_BALANCE
     {
       struct request_t
       {
-        BEGIN_KV_SERIALIZE_MAP()
-        END_KV_SERIALIZE_MAP()
+	uint32_t account_index;
+	std::set<uint32_t> address_indices;
+	bool all_accounts;
+	bool strict;
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(address_indices)
+	  KV_SERIALIZE_OPT(all_accounts, false)
+	  KV_SERIALIZE_OPT(strict, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct per_subaddress_info
+      {
+	uint32_t account_index;
+	uint32_t address_index;
+	std::string address;
+	uint64_t balance;
+	uint64_t unlocked_balance;
+	std::string label;
+	uint64_t num_unspent_outputs;
+	uint64_t blocks_to_unlock;
+	uint64_t time_to_unlock;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(address_index)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(balance)
+	  KV_SERIALIZE(unlocked_balance)
+	  KV_SERIALIZE(label)
+	  KV_SERIALIZE(num_unspent_outputs)
+	  KV_SERIALIZE(blocks_to_unlock)
+	  KV_SERIALIZE(time_to_unlock)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response_t
+      {
+	uint64_t 	 balance;
+	uint64_t 	 unlocked_balance;
+	bool       multisig_import_needed;
+	std::vector<per_subaddress_info> per_subaddress;
+	uint64_t   blocks_to_unlock;
+	uint64_t   time_to_unlock;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(balance)
+	  KV_SERIALIZE(unlocked_balance)
+	  KV_SERIALIZE(multisig_import_needed)
+	  KV_SERIALIZE(per_subaddress)
+	  KV_SERIALIZE(blocks_to_unlock)
+	  KV_SERIALIZE(time_to_unlock)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_ADDRESS
+    {
+      struct request_t
+      {
+	uint32_t account_index;
+	std::vector<uint32_t> address_index;
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(address_index)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct address_info
+      {
+	std::string address;
+	std::string label;
+	uint32_t address_index;
+	bool used;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(label)
+	  KV_SERIALIZE(address_index)
+	  KV_SERIALIZE(used)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response_t
+      {
+	std::string address;                  // to remain compatible with older RPC format
+	std::vector<address_info> addresses;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(addresses)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_ADDRESS_INDEX
+    {
+      struct request_t
+      {
+	std::string address;
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  END_KV_SERIALIZE_MAP()
       };
       typedef epee::misc_utils::struct_init<request_t> request;
 
       struct response_t
       {
-        uint64_t  height;
-        BEGIN_KV_SERIALIZE_MAP()
-          KV_SERIALIZE(height)
-        END_KV_SERIALIZE_MAP()
+	cryptonote::subaddress_index index;
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(index)
+	  END_KV_SERIALIZE_MAP()
       };
       typedef epee::misc_utils::struct_init<response_t> response;
     };
 
-  struct transfer_destination
-  {
-    uint64_t amount;
-    std::string address;
-    BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE(amount)
-      KV_SERIALIZE(address)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_FREEZE
-  {
-    struct request_t
+    struct COMMAND_RPC_CREATE_ADDRESS
     {
-      std::string key_image;
+      struct request_t
+      {
+	uint32_t    account_index;
+	uint32_t    count;
+	std::string label;
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key_image)
-      END_KV_SERIALIZE_MAP()
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE_OPT(count, 1U)
+	  KV_SERIALIZE(label)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string              address;
+	uint32_t                 address_index;
+	std::vector<std::string> addresses;
+	std::vector<uint32_t>    address_indices;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(address_index)
+	  KV_SERIALIZE(addresses)
+	  KV_SERIALIZE(address_indices)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    struct response_t
+    struct COMMAND_RPC_LABEL_ADDRESS
     {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
+      struct request_t
+      {
+	cryptonote::subaddress_index index;
+	std::string label;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(index)
+	  KV_SERIALIZE(label)
+	  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;
     };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
 
-  struct COMMAND_RPC_THAW
-  {
-    struct request_t
+    struct COMMAND_RPC_GET_ACCOUNTS
     {
-      std::string key_image;
+      struct request_t
+      {
+	std::string tag;      // all accounts if empty, otherwise those accounts with this tag
+	bool strict_balances;
+	bool regexp; // allow regular expression filters if set to true
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key_image)
-      END_KV_SERIALIZE_MAP()
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tag)
+	  KV_SERIALIZE_OPT(strict_balances, false)
+	  KV_SERIALIZE_OPT(regexp, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct subaddress_account_info
+      {
+	uint32_t account_index;
+	std::string base_address;
+	uint64_t balance;
+	uint64_t unlocked_balance;
+	std::string label;
+	std::string tag;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(base_address)
+	  KV_SERIALIZE(balance)
+	  KV_SERIALIZE(unlocked_balance)
+	  KV_SERIALIZE(label)
+	  KV_SERIALIZE(tag)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response_t
+      {
+	uint64_t total_balance;
+	uint64_t total_unlocked_balance;
+	std::vector<subaddress_account_info> subaddress_accounts;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(total_balance)
+	  KV_SERIALIZE(total_unlocked_balance)
+	  KV_SERIALIZE(subaddress_accounts)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    struct response_t
+    struct COMMAND_RPC_CREATE_ACCOUNT
     {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
+      struct request_t
+      {
+	std::string label;
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(label)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint32_t account_index;
+	std::string address;      // the 0-th address for convenience
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(address)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
     };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
 
-  struct COMMAND_RPC_FROZEN
-  {
-    struct request_t
+    struct COMMAND_RPC_LABEL_ACCOUNT
     {
-      std::string key_image;
+      struct request_t
+      {
+	uint32_t account_index;
+	std::string label;
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key_image)
-      END_KV_SERIALIZE_MAP()
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(label)
+	  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;
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    struct response_t
+    struct COMMAND_RPC_GET_ACCOUNT_TAGS
     {
-      bool frozen;
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(frozen)
-      END_KV_SERIALIZE_MAP()
+      struct account_tag_info
+      {
+	std::string tag;
+	std::string label;
+	std::vector<uint32_t> accounts;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tag)
+	  KV_SERIALIZE(label)
+	  KV_SERIALIZE(accounts)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response_t
+      {
+	std::vector<account_tag_info> account_tags;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(account_tags)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
     };
-    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 amounts_list
-  {
-    std::list<uint64_t> amounts;
-
-    bool operator==(const amounts_list& other) const { return amounts == other.amounts; }
-
-    BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE(amounts)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct single_transfer_response
-  {
-    std::string tx_hash;
-    std::string tx_key;
-    uint64_t amount;
-    amounts_list amounts_by_dest;
-    uint64_t fee;
-    uint64_t weight;
-    std::string tx_blob;
-    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)
-      KV_SERIALIZE(tx_key)
-      KV_SERIALIZE(amount)
-      KV_SERIALIZE_OPT(amounts_by_dest, decltype(amounts_by_dest)())
-      KV_SERIALIZE(fee)
-      KV_SERIALIZE(weight)
-      KV_SERIALIZE(tx_blob)
-      KV_SERIALIZE(tx_metadata)
-      KV_SERIALIZE(multisig_txset)
-      KV_SERIALIZE(unsigned_txset)
-      KV_SERIALIZE(spent_key_images)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_TRANSFER
-  {
-    struct request_t
+    struct COMMAND_RPC_TAG_ACCOUNTS
     {
-      std::list<transfer_destination> destinations;
-      uint32_t account_index;
-      std::set<uint32_t> subaddr_indices;
-      std::set<uint32_t> subtract_fee_from_outputs;
-      uint32_t priority;
-      uint64_t ring_size;
-      uint64_t unlock_time;
-      std::string payment_id;
-      bool get_tx_key;
-      bool do_not_relay;
-      bool get_tx_hex;
-      bool get_tx_metadata;
+      struct request_t
+      {
+	std::string tag;
+	std::set<uint32_t> accounts;
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(destinations)
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(subaddr_indices)
-        KV_SERIALIZE_OPT(subtract_fee_from_outputs, decltype(subtract_fee_from_outputs)())
-        KV_SERIALIZE(priority)
-        KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
-        KV_SERIALIZE(unlock_time)
-        KV_SERIALIZE(payment_id)
-        KV_SERIALIZE(get_tx_key)
-        KV_SERIALIZE_OPT(do_not_relay, false)
-        KV_SERIALIZE_OPT(get_tx_hex, false)
-        KV_SERIALIZE_OPT(get_tx_metadata, false)
-      END_KV_SERIALIZE_MAP()
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tag)
+	  KV_SERIALIZE(accounts)
+	  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;
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    typedef single_transfer_response response_t;
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct split_transfer_response
-  {
-    std::list<std::string> tx_hash_list;
-    std::list<std::string> tx_key_list;
-    std::list<uint64_t> amount_list;
-    std::list<amounts_list> amounts_by_dest_list;
-    std::list<uint64_t> fee_list;
-    std::list<uint64_t> weight_list;
-    std::list<std::string> tx_blob_list;
-    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)
-      KV_SERIALIZE(tx_key_list)
-      KV_SERIALIZE(amount_list)
-      KV_SERIALIZE_OPT(amounts_by_dest_list, decltype(amounts_by_dest_list)())
-      KV_SERIALIZE(fee_list)
-      KV_SERIALIZE(weight_list)
-      KV_SERIALIZE(tx_blob_list)
-      KV_SERIALIZE(tx_metadata_list)
-      KV_SERIALIZE(multisig_txset)
-      KV_SERIALIZE(unsigned_txset)
-      KV_SERIALIZE(spent_key_images_list)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_TRANSFER_SPLIT
-  {
-    struct request_t
+    struct COMMAND_RPC_UNTAG_ACCOUNTS
     {
-      std::list<transfer_destination> destinations;
-      uint32_t account_index;
-      std::set<uint32_t> subaddr_indices;
-      uint32_t priority;
-      uint64_t ring_size;
-      uint64_t unlock_time;
-      std::string payment_id;
-      bool get_tx_keys;
-      bool do_not_relay;
-      bool get_tx_hex;
-      bool get_tx_metadata;
+      struct request_t
+      {
+	std::set<uint32_t> accounts;
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(destinations)
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(subaddr_indices)
-        KV_SERIALIZE(priority)
-        KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
-        KV_SERIALIZE(unlock_time)
-        KV_SERIALIZE(payment_id)
-        KV_SERIALIZE(get_tx_keys)
-        KV_SERIALIZE_OPT(do_not_relay, false)
-        KV_SERIALIZE_OPT(get_tx_hex, false)
-        KV_SERIALIZE_OPT(get_tx_metadata, false)
-      END_KV_SERIALIZE_MAP()
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(accounts)
+	  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;
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    typedef split_transfer_response response_t;
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_DESCRIBE_TRANSFER
-  {
-    struct recipient
+    struct COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION
+    {
+      struct request_t
+      {
+	std::string tag;
+	std::string description;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tag)
+	  KV_SERIALIZE(description)
+	  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_GET_HEIGHT
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t  height;
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(height)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct transfer_destination
     {
-      std::string address;
       uint64_t amount;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(amount)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct transfer_description
-    {
-      uint64_t amount_in;
-      uint64_t amount_out;
-      uint32_t ring_size;
-      uint64_t unlock_time;
-      std::list<recipient> recipients;
-      std::string payment_id;
-      uint64_t change_amount;
-      std::string change_address;
-      uint64_t fee;
-      uint32_t dummy_outputs;
-      std::string extra;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(amount_in)
-        KV_SERIALIZE(amount_out)
-        KV_SERIALIZE(ring_size)
-        KV_SERIALIZE(unlock_time)
-        KV_SERIALIZE(recipients)
-        KV_SERIALIZE(payment_id)
-        KV_SERIALIZE(change_amount)
-        KV_SERIALIZE(change_address)
-        KV_SERIALIZE(fee)
-        KV_SERIALIZE(dummy_outputs)
-        KV_SERIALIZE(extra)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct txset_summary
-    {
-      uint64_t amount_in;
-      uint64_t amount_out;
-      std::list<recipient> recipients;
-      uint64_t change_amount;
-      std::string change_address;
-      uint64_t fee;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(amount_in)
-        KV_SERIALIZE(amount_out)
-        KV_SERIALIZE(recipients)
-        KV_SERIALIZE(change_amount)
-        KV_SERIALIZE(change_address)
-        KV_SERIALIZE(fee)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct request_t
-    {
-      std::string unsigned_txset;
-      std::string multisig_txset;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(unsigned_txset)
-        KV_SERIALIZE(multisig_txset)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<transfer_description> desc;
-      struct txset_summary summary;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(summary)
-        KV_SERIALIZE(desc)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SIGN_TRANSFER
-  {
-    struct request_t
-    {
-      std::string unsigned_txset;
-      bool export_raw;
-      bool get_tx_keys;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(unsigned_txset)
-        KV_SERIALIZE_OPT(export_raw, false)
-        KV_SERIALIZE_OPT(get_tx_keys, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string signed_txset;
-      std::list<std::string> tx_hash_list;
-      std::list<std::string> tx_raw_list;
-      std::list<std::string> tx_key_list;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(signed_txset)
-        KV_SERIALIZE(tx_hash_list)
-        KV_SERIALIZE(tx_raw_list)
-        KV_SERIALIZE(tx_key_list)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SUBMIT_TRANSFER
-  {
-    struct request_t
-    {
-      std::string tx_data_hex;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_data_hex)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<std::string> tx_hash_list;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_hash_list)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SWEEP_DUST
-  {
-    struct request_t
-    {
-      bool get_tx_keys;
-      bool do_not_relay;
-      bool get_tx_hex;
-      bool get_tx_metadata;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(get_tx_keys)
-        KV_SERIALIZE_OPT(do_not_relay, false)
-        KV_SERIALIZE_OPT(get_tx_hex, false)
-        KV_SERIALIZE_OPT(get_tx_metadata, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    typedef split_transfer_response response_t;
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SWEEP_ALL
-  {
-    struct request_t
-    {
       std::string address;
-      uint32_t account_index;
-      std::set<uint32_t> subaddr_indices;
-      bool subaddr_indices_all;
-      uint32_t priority;
-      uint64_t ring_size;
-      uint64_t outputs;
-      uint64_t unlock_time;
-      std::string payment_id;
-      bool get_tx_keys;
-      uint64_t below_amount;
-      bool do_not_relay;
-      bool get_tx_hex;
-      bool get_tx_metadata;
-
       BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(subaddr_indices)
-        KV_SERIALIZE_OPT(subaddr_indices_all, false)
-        KV_SERIALIZE(priority)
-        KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
-        KV_SERIALIZE_OPT(outputs, (uint64_t)1)
-        KV_SERIALIZE(unlock_time)
-        KV_SERIALIZE(payment_id)
-        KV_SERIALIZE(get_tx_keys)
-        KV_SERIALIZE(below_amount)
-        KV_SERIALIZE_OPT(do_not_relay, false)
-        KV_SERIALIZE_OPT(get_tx_hex, false)
-        KV_SERIALIZE_OPT(get_tx_metadata, false)
-      END_KV_SERIALIZE_MAP()
+	KV_SERIALIZE(amount)
+	KV_SERIALIZE(address)
+	END_KV_SERIALIZE_MAP()
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    typedef split_transfer_response response_t;
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SWEEP_SINGLE
-  {
-    struct request_t
+    struct COMMAND_RPC_FREEZE
     {
-      std::string address;
-      uint32_t priority;
-      uint64_t ring_size;
-      uint64_t outputs;
-      uint64_t unlock_time;
-      std::string payment_id;
-      bool get_tx_key;
-      std::string key_image;
-      bool do_not_relay;
-      bool get_tx_hex;
-      bool get_tx_metadata;
+      struct request_t
+      {
+	std::string key_image;
 
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(priority)
-        KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
-        KV_SERIALIZE_OPT(outputs, (uint64_t)1)
-        KV_SERIALIZE(unlock_time)
-        KV_SERIALIZE(payment_id)
-        KV_SERIALIZE(get_tx_key)
-        KV_SERIALIZE(key_image)
-        KV_SERIALIZE_OPT(do_not_relay, false)
-        KV_SERIALIZE_OPT(get_tx_hex, false)
-        KV_SERIALIZE_OPT(get_tx_metadata, false)
-      END_KV_SERIALIZE_MAP()
+	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;
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    typedef single_transfer_response response_t;
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_RELAY_TX
-  {
-    struct request_t
+    struct COMMAND_RPC_THAW
     {
-      std::string hex;
+      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(hex)
-      END_KV_SERIALIZE_MAP()
+	KV_SERIALIZE(key_images)
+	END_KV_SERIALIZE_MAP()
     };
-    typedef epee::misc_utils::struct_init<request_t> request;
 
-    struct response_t
+    struct amounts_list
+    {
+      std::list<uint64_t> amounts;
+
+      bool operator==(const amounts_list& other) const { return amounts == other.amounts; }
+
+      BEGIN_KV_SERIALIZE_MAP()
+	KV_SERIALIZE(amounts)
+	END_KV_SERIALIZE_MAP()
+    };
+
+    struct single_transfer_response
     {
       std::string tx_hash;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_hash)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_STORE
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      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 payment_details
-  {
-    std::string payment_id;
-    std::string tx_hash;
-    uint64_t amount;
-    uint64_t block_height;
-    uint64_t unlock_time;
-    bool locked;
-    cryptonote::subaddress_index subaddr_index;
-    std::string address;
-
-    BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE(payment_id)
-      KV_SERIALIZE(tx_hash)
-      KV_SERIALIZE(amount)
-      KV_SERIALIZE(block_height)
-      KV_SERIALIZE(unlock_time)
-      KV_SERIALIZE(locked)
-      KV_SERIALIZE(subaddr_index)
-      KV_SERIALIZE(address)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_GET_PAYMENTS
-  {
-    struct request_t
-    {
-      std::string payment_id;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(payment_id)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<payment_details> payments;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(payments)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_BULK_PAYMENTS
-  {
-    struct request_t
-    {
-      std::vector<std::string> payment_ids;
-      uint64_t min_block_height;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(payment_ids)
-        KV_SERIALIZE(min_block_height)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<payment_details> payments;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(payments)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-  
-  struct transfer_details
-  {
-    uint64_t amount;
-    bool spent;
-    uint64_t global_index;
-    std::string tx_hash;
-    cryptonote::subaddress_index subaddr_index;
-    std::string key_image;
-    std::string pubkey; // owned output public key found
-    uint64_t block_height;
-    bool frozen;
-    bool unlocked;
-
-    BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE(amount)
-      KV_SERIALIZE(spent)
-      KV_SERIALIZE(global_index)
-      KV_SERIALIZE(tx_hash)
-      KV_SERIALIZE(subaddr_index)
-      KV_SERIALIZE(key_image)
-      KV_SERIALIZE(pubkey)
-      KV_SERIALIZE(block_height)
-      KV_SERIALIZE(frozen)
-      KV_SERIALIZE(unlocked)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_INCOMING_TRANSFERS
-  {
-    struct request_t
-    {
-      std::string transfer_type;
-      uint32_t account_index;
-      std::set<uint32_t> subaddr_indices;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(transfer_type)
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(subaddr_indices)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<transfer_details> transfers;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(transfers)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  //JSON RPC V2
-  struct COMMAND_RPC_QUERY_KEY
-  {
-    struct request_t
-    {
-      std::string key_type;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key_type)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string key;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_MAKE_INTEGRATED_ADDRESS
-  {
-    struct request_t
-    {
-      std::string standard_address;
-      std::string payment_id;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(standard_address)
-        KV_SERIALIZE(payment_id)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string integrated_address;
-      std::string payment_id;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(integrated_address)
-        KV_SERIALIZE(payment_id)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS
-  {
-    struct request_t
-    {
-      std::string integrated_address;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(integrated_address)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string standard_address;
-      std::string payment_id;
-      bool is_subaddress;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(standard_address)
-        KV_SERIALIZE(payment_id)
-        KV_SERIALIZE(is_subaddress)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_STOP_WALLET
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      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_RESCAN_BLOCKCHAIN
-  {
-    struct request_t
-    {
-      bool hard;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE_OPT(hard, false)
-      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_SET_TX_NOTES
-  {
-    struct request_t
-    {
-      std::list<std::string> txids;
-      std::list<std::string> notes;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txids)
-        KV_SERIALIZE(notes)
-      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_GET_TX_NOTES
-  {
-    struct request_t
-    {
-      std::list<std::string> txids;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txids)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<std::string> notes;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(notes)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SET_ATTRIBUTE
-  {
-    struct request_t
-    {
-      std::string key;
-      std::string value;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key)
-        KV_SERIALIZE(value)
-      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_GET_ATTRIBUTE
-  {
-    struct request_t
-    {
-
-      std::string key;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string value;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(value)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_TX_KEY
-  {
-    struct request_t
-    {
-      std::string txid;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
       std::string tx_key;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_key)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CHECK_TX_KEY
-  {
-    struct request_t
-    {
-      std::string txid;
-      std::string tx_key;
-      std::string address;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-        KV_SERIALIZE(tx_key)
-        KV_SERIALIZE(address)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint64_t received;
-      bool in_pool;
-      uint64_t confirmations;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(received)
-        KV_SERIALIZE(in_pool)
-        KV_SERIALIZE(confirmations)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_TX_PROOF
-  {
-    struct request_t
-    {
-      std::string txid;
-      std::string address;
-      std::string message;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(message)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CHECK_TX_PROOF
-  {
-    struct request_t
-    {
-      std::string txid;
-      std::string address;
-      std::string message;
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(message)
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      bool good;
-      uint64_t received;
-      bool in_pool;
-      uint64_t confirmations;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(good)
-        KV_SERIALIZE(received)
-        KV_SERIALIZE(in_pool)
-        KV_SERIALIZE(confirmations)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  typedef std::vector<uint64_t> amounts_container;
-  struct transfer_entry
-  {
-    std::string txid;
-    std::string payment_id;
-    uint64_t height;
-    uint64_t timestamp;
-    uint64_t amount;
-    amounts_container amounts;
-    uint64_t fee;
-    std::string note;
-    std::list<transfer_destination> destinations;
-    std::string type;
-    uint64_t unlock_time;
-    bool locked;
-    cryptonote::subaddress_index subaddr_index;
-    std::vector<cryptonote::subaddress_index> subaddr_indices;
-    std::string address;
-    bool double_spend_seen;
-    uint64_t confirmations;
-    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(unlock_time)
-      KV_SERIALIZE(locked)
-      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)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_GET_SPEND_PROOF
-  {
-    struct request_t
-    {
-      std::string txid;
-      std::string message;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-        KV_SERIALIZE(message)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CHECK_SPEND_PROOF
-  {
-    struct request_t
-    {
-      std::string txid;
-      std::string message;
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-        KV_SERIALIZE(message)
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      bool good;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(good)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_RESERVE_PROOF
-  {
-    struct request_t
-    {
-      bool all;
-      uint32_t account_index;     // ignored when `all` is true
-      uint64_t amount;            // ignored when `all` is true
-      std::string message;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(all)
-        KV_SERIALIZE(account_index)
-        KV_SERIALIZE(amount)
-        KV_SERIALIZE(message)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CHECK_RESERVE_PROOF
-  {
-    struct request_t
-    {
-      std::string address;
-      std::string message;
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(message)
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      bool good;
-      uint64_t total;
-      uint64_t spent;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(good)
-        KV_SERIALIZE(total)
-        KV_SERIALIZE(spent)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_TRANSFERS
-  {
-    struct request_t
-    {
-      bool in;
-      bool out;
-      bool pending;
-      bool failed;
-      bool pool;
-
-      bool filter_by_height;
-      uint64_t min_height;
-      uint64_t max_height;
-      uint32_t account_index;
-      std::set<uint32_t> subaddr_indices;
-      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)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<transfer_entry> in;
-      std::list<transfer_entry> out;
-      std::list<transfer_entry> pending;
-      std::list<transfer_entry> failed;
-      std::list<transfer_entry> pool;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        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;
-  };
-
-  struct COMMAND_RPC_GET_TRANSFER_BY_TXID
-  {
-    struct request_t
-    {
-      std::string txid;
-      uint32_t account_index;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txid)
-        KV_SERIALIZE_OPT(account_index, (uint32_t)0)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      transfer_entry transfer;
-      std::list<transfer_entry> transfers;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(transfer)
-        KV_SERIALIZE(transfers)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SIGN
-  {
-    struct request_t
-    {
-      std::string data;
-      uint32_t account_index;
-      uint32_t address_index;
-      std::string signature_type;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(data)
-        KV_SERIALIZE_OPT(account_index, 0u)
-        KV_SERIALIZE_OPT(address_index, 0u)
-        KV_SERIALIZE(signature_type)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_VERIFY
-  {
-    struct request_t
-    {
-      std::string data;
-      std::string address;
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(data)
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      bool good;
-      unsigned version;
-      bool old;
-      std::string signature_type;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        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;
-  };
-
-  struct COMMAND_RPC_EXPORT_OUTPUTS
-  {
-    struct request_t
-    {
-      bool all;
-      uint32_t start;
-      uint32_t count;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(all)
-        KV_SERIALIZE_OPT(start, 0u)
-        KV_SERIALIZE_OPT(count, 0xffffffffu)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string outputs_data_hex;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(outputs_data_hex)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_IMPORT_OUTPUTS
-  {
-    struct request_t
-    {
-      std::string outputs_data_hex;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(outputs_data_hex)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint64_t num_imported;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(num_imported)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_EXPORT_KEY_IMAGES
-  {
-    struct request_t
-    {
-      bool all;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE_OPT(all, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct signed_key_image
-    {
-      std::string key_image;
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key_image)
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response_t
-    {
-      uint32_t offset;
-      std::vector<signed_key_image> signed_key_images;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(offset)
-        KV_SERIALIZE(signed_key_images)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_IMPORT_KEY_IMAGES
-  {
-    struct signed_key_image
-    {
-      std::string key_image;
-      std::string signature;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(key_image)
-        KV_SERIALIZE(signature)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct request_t
-    {
-      uint32_t offset;
-      std::vector<signed_key_image> signed_key_images;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        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;
-
-    struct response_t
-    {
-      uint64_t height;
-      uint64_t spent;
-      uint64_t unspent;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(height)
-        KV_SERIALIZE(spent)
-        KV_SERIALIZE(unspent)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct uri_spec
-  {
-    std::string address;
-    std::string payment_id;
-    uint64_t amount;
-    std::string tx_description;
-    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)
-    END_KV_SERIALIZE_MAP()
-  };
-
-  struct COMMAND_RPC_MAKE_URI
-  {
-    struct request_t: public uri_spec
-    {
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string uri;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(uri)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_PARSE_URI
-  {
-    struct request_t
-    {
-      std::string uri;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(uri)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uri_spec uri;
-      std::vector<std::string> unknown_parameters;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(uri)
-        KV_SERIALIZE(unknown_parameters)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_ADD_ADDRESS_BOOK_ENTRY
-  {
-    struct request_t
-    {
-      std::string address;
-      std::string description;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(description)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint64_t index;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(index)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_EDIT_ADDRESS_BOOK_ENTRY
-  {
-    struct request_t
-    {
-      uint64_t index;
-      bool set_address;
-      std::string address;
-      bool set_description;
-      std::string description;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(index)
-        KV_SERIALIZE(set_address)
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(set_description)
-        KV_SERIALIZE(description)
-      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_GET_ADDRESS_BOOK_ENTRY
-  {
-    struct request_t
-    {
-      std::list<uint64_t> entries;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(entries)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct entry
-    {
-      uint64_t index;
-      std::string address;
-      std::string description;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(index)
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(description)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response_t
-    {
-      std::vector<entry> entries;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(entries)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_DELETE_ADDRESS_BOOK_ENTRY
-  {
-    struct request_t
-    {
-      uint64_t index;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(index)
-      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_RESCAN_SPENT
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      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_REFRESH
-  {
-    struct request_t
-    {
-      uint64_t start_height;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE_OPT(start_height, (uint64_t) 0)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint64_t blocks_fetched;
-      bool received_money;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(blocks_fetched)
-        KV_SERIALIZE(received_money)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_AUTO_REFRESH
-  {
-    struct request_t
-    {
-      bool enable;
-      uint32_t period; // seconds
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE_OPT(enable, true)
-        KV_SERIALIZE_OPT(period, (uint32_t)0)
-      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_SCAN_TX
-  {
-    struct request_t
-    {
-      std::list<std::string> txids;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(txids)
-      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_START_MINING
-  {
-    struct request_t
-    {
-      uint64_t    threads_count;
-      bool        do_background_mining;
-      bool        ignore_battery;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(threads_count)
-        KV_SERIALIZE(do_background_mining)        
-        KV_SERIALIZE(ignore_battery)        
-      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_STOP_MINING
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      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_GET_LANGUAGES
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::vector<std::string> languages;
-      std::vector<std::string> languages_local;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(languages)
-        KV_SERIALIZE(languages_local)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_CREATE_WALLET
-  {
-    struct request_t
-    {
-      std::string filename;
-      std::string password;
-      std::string language;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(filename)
-        KV_SERIALIZE(password)
-        KV_SERIALIZE(language)
-      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_OPEN_WALLET
-  {
-    struct request_t
-    {
-      std::string filename;
-      std::string password;
-      bool autosave_current;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(filename)
-        KV_SERIALIZE(password)
-        KV_SERIALIZE_OPT(autosave_current, true)
-      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_CLOSE_WALLET
-  {
-    struct request_t
-    {
-      bool autosave_current;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE_OPT(autosave_current, true)
-      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_CHANGE_WALLET_PASSWORD
-  {
-    struct request_t
-    {
-      std::string old_password;
-      std::string new_password;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(old_password)
-        KV_SERIALIZE(new_password)
-      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_GENERATE_FROM_KEYS
-  {
-    struct request
-    {
-      uint64_t restore_height;
-      std::string filename;
-      std::string address;
-      std::string spendkey;
-      std::string viewkey;
-      std::string password;
-      bool autosave_current;
-      std::string language;
-
-      BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
-      KV_SERIALIZE(filename)
-      KV_SERIALIZE(address)
-      KV_SERIALIZE(spendkey)
-      KV_SERIALIZE(viewkey)
-      KV_SERIALIZE(password)
-      KV_SERIALIZE_OPT(autosave_current, true)
-      KV_SERIALIZE(language)
-      END_KV_SERIALIZE_MAP()
-    };
-
-    struct response
-    {
-      std::string address;
-      std::string info;
-
-      BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE(address)
-      KV_SERIALIZE(info)
-      END_KV_SERIALIZE_MAP()
-    };
-  };
-
-  struct COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET
-  {
-    struct request_t
-    {
-      uint64_t restore_height;
-      std::string filename;
-      std::string seed;
-      std::string seed_offset;
-      std::string password;
-      std::string language;
-      bool autosave_current;
-      bool enable_multisig_experimental;
-
-      BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
-      KV_SERIALIZE(filename)
-      KV_SERIALIZE(seed)
-      KV_SERIALIZE(seed_offset)
-      KV_SERIALIZE(password)
-      KV_SERIALIZE(language)
-      KV_SERIALIZE_OPT(autosave_current, true)
-      KV_SERIALIZE_OPT(enable_multisig_experimental, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string address;
-      std::string seed;
-      std::string info;
-      bool was_deprecated;
-
-      BEGIN_KV_SERIALIZE_MAP()
-      KV_SERIALIZE(address)
-      KV_SERIALIZE(seed)
-      KV_SERIALIZE(info)
-      KV_SERIALIZE(was_deprecated)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-  
-  struct COMMAND_RPC_IS_MULTISIG
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      bool multisig;
-      bool kex_is_done;
-      bool ready;
-      uint32_t threshold;
-      uint32_t total;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(multisig)
-        KV_SERIALIZE(kex_is_done)
-        KV_SERIALIZE(ready)
-        KV_SERIALIZE(threshold)
-        KV_SERIALIZE(total)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_PREPARE_MULTISIG
-  {
-    struct request_t
-    {
-      bool enable_multisig_experimental;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE_OPT(enable_multisig_experimental, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string multisig_info;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(multisig_info)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_MAKE_MULTISIG
-  {
-    struct request_t
-    {
-      std::vector<std::string> multisig_info;
-      uint32_t threshold;
-      std::string password;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(multisig_info)
-        KV_SERIALIZE(threshold)
-        KV_SERIALIZE(password)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string address;
-      std::string multisig_info;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(multisig_info)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_EXPORT_MULTISIG
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string info;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(info)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_IMPORT_MULTISIG
-  {
-    struct request_t
-    {
-      std::vector<std::string> info;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(info)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint64_t n_outputs;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(n_outputs)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_FINALIZE_MULTISIG
-  {
-    // NOP
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      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_EXCHANGE_MULTISIG_KEYS
-  {
-    struct request_t
-    {
-      std::string password;
-      std::vector<std::string> multisig_info;
-      bool force_update_use_with_caution;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(password)
-        KV_SERIALIZE(multisig_info)
-        KV_SERIALIZE_OPT(force_update_use_with_caution, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string address;
-      std::string multisig_info;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(multisig_info)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SIGN_MULTISIG
-  {
-    struct request_t
-    {
-      std::string tx_data_hex;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_data_hex)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string tx_data_hex;
-      std::list<std::string> tx_hash_list;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_data_hex)
-        KV_SERIALIZE(tx_hash_list)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SUBMIT_MULTISIG
-  {
-    struct request_t
-    {
-      std::string tx_data_hex;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_data_hex)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::list<std::string> tx_hash_list;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(tx_hash_list)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_GET_VERSION
-  {
-    struct request_t
-    {
-      BEGIN_KV_SERIALIZE_MAP()
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint32_t version;
-      bool release;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(version)
-        KV_SERIALIZE(release)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_VALIDATE_ADDRESS
-  {
-    struct request_t
-    {
-      std::string address;
-      bool any_net_type;
-      bool allow_openalias;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE_OPT(any_net_type, false)
-        KV_SERIALIZE_OPT(allow_openalias, false)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      bool valid;
-      bool integrated;
-      bool subaddress;
-      std::string nettype;
-      std::string openalias_address;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(valid)
-        KV_SERIALIZE(integrated)
-        KV_SERIALIZE(subaddress)
-        KV_SERIALIZE(nettype)
-        KV_SERIALIZE(openalias_address)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_SET_DAEMON
-  {
-    struct request_t
-    {
-      std::string address;
-      std::string username;
-      std::string password;
-      bool trusted;
-      std::string ssl_support; // disabled, enabled, autodetect
-      std::string ssl_private_key_path;
-      std::string ssl_certificate_path;
-      std::string ssl_ca_file;
-      std::vector<std::string> ssl_allowed_fingerprints;
-      bool ssl_allow_any_cert;
-      std::string proxy;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(address)
-        KV_SERIALIZE(username)
-        KV_SERIALIZE(password)
-        KV_SERIALIZE_OPT(trusted, false)
-        KV_SERIALIZE_OPT(ssl_support, (std::string)"autodetect")
-        KV_SERIALIZE(ssl_private_key_path)
-        KV_SERIALIZE(ssl_certificate_path)
-        KV_SERIALIZE(ssl_ca_file)
-        KV_SERIALIZE(ssl_allowed_fingerprints)
-        KV_SERIALIZE_OPT(ssl_allow_any_cert, false)
-        KV_SERIALIZE_OPT(proxy, (std::string)"")
-      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_SET_LOG_LEVEL
-  {
-    struct request_t
-    {
-      int8_t level;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(level)
-      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_SET_LOG_CATEGORIES
-  {
-    struct request_t
-    {
-      std::string categories;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(categories)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      std::string categories;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(categories)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<response_t> response;
-  };
-
-  struct COMMAND_RPC_ESTIMATE_TX_SIZE_AND_WEIGHT
-  {
-    struct request_t
-    {
-      uint32_t n_inputs;
-      uint32_t n_outputs;
-      uint32_t ring_size;
-      bool rct;
-
-      BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(n_inputs)
-        KV_SERIALIZE(n_outputs)
-        KV_SERIALIZE_OPT(ring_size, 0u)
-        KV_SERIALIZE_OPT(rct, true)
-      END_KV_SERIALIZE_MAP()
-    };
-    typedef epee::misc_utils::struct_init<request_t> request;
-
-    struct response_t
-    {
-      uint64_t size;
+      uint64_t amount;
+      amounts_list amounts_by_dest;
+      uint64_t fee;
       uint64_t weight;
+      std::string tx_blob;
+      std::string tx_metadata;
+      std::string multisig_txset;
+      std::string unsigned_txset;
+      key_image_list spent_key_images;
 
       BEGIN_KV_SERIALIZE_MAP()
-        KV_SERIALIZE(size)
-        KV_SERIALIZE(weight)
-      END_KV_SERIALIZE_MAP()
+	KV_SERIALIZE(tx_hash)
+	KV_SERIALIZE(tx_key)
+	KV_SERIALIZE(amount)
+	KV_SERIALIZE_OPT(amounts_by_dest, decltype(amounts_by_dest)())
+	KV_SERIALIZE(fee)
+	KV_SERIALIZE(weight)
+	KV_SERIALIZE(tx_blob)
+	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;
-  };
 
-}
+    struct COMMAND_RPC_TRANSFER
+    {
+      struct request_t
+      {
+	std::list<transfer_destination> destinations;
+	uint32_t account_index;
+	std::set<uint32_t> subaddr_indices;
+	std::set<uint32_t> subtract_fee_from_outputs;
+	uint32_t priority;
+	uint64_t ring_size;
+	uint64_t unlock_time;
+	std::string payment_id;
+	bool get_tx_key;
+	bool do_not_relay;
+	bool get_tx_hex;
+	bool get_tx_metadata;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(destinations)
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(subaddr_indices)
+	  KV_SERIALIZE_OPT(subtract_fee_from_outputs, decltype(subtract_fee_from_outputs)())
+	  KV_SERIALIZE(priority)
+	  KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
+	  KV_SERIALIZE(unlock_time)
+	  KV_SERIALIZE(payment_id)
+	  KV_SERIALIZE(get_tx_key)
+	  KV_SERIALIZE_OPT(do_not_relay, false)
+	  KV_SERIALIZE_OPT(get_tx_hex, false)
+	  KV_SERIALIZE_OPT(get_tx_metadata, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      typedef single_transfer_response response_t;
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct split_transfer_response
+    {
+      std::list<std::string> tx_hash_list;
+      std::list<std::string> tx_key_list;
+      std::list<uint64_t> amount_list;
+      std::list<amounts_list> amounts_by_dest_list;
+      std::list<uint64_t> fee_list;
+      std::list<uint64_t> weight_list;
+      std::list<std::string> tx_blob_list;
+      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)
+	KV_SERIALIZE(tx_key_list)
+	KV_SERIALIZE(amount_list)
+	KV_SERIALIZE_OPT(amounts_by_dest_list, decltype(amounts_by_dest_list)())
+	KV_SERIALIZE(fee_list)
+	KV_SERIALIZE(weight_list)
+	KV_SERIALIZE(tx_blob_list)
+	KV_SERIALIZE(tx_metadata_list)
+	KV_SERIALIZE(multisig_txset)
+	KV_SERIALIZE(unsigned_txset)
+	KV_SERIALIZE(spent_key_images_list)
+	END_KV_SERIALIZE_MAP()
+    };
+
+    struct COMMAND_RPC_TRANSFER_SPLIT
+    {
+      struct request_t
+      {
+	std::list<transfer_destination> destinations;
+	uint32_t account_index;
+	std::set<uint32_t> subaddr_indices;
+	uint32_t priority;
+	uint64_t ring_size;
+	uint64_t unlock_time;
+	std::string payment_id;
+	bool get_tx_keys;
+	bool do_not_relay;
+	bool get_tx_hex;
+	bool get_tx_metadata;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(destinations)
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(subaddr_indices)
+	  KV_SERIALIZE(priority)
+	  KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
+	  KV_SERIALIZE(unlock_time)
+	  KV_SERIALIZE(payment_id)
+	  KV_SERIALIZE(get_tx_keys)
+	  KV_SERIALIZE_OPT(do_not_relay, false)
+	  KV_SERIALIZE_OPT(get_tx_hex, false)
+	  KV_SERIALIZE_OPT(get_tx_metadata, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      typedef split_transfer_response response_t;
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_DESCRIBE_TRANSFER
+    {
+      struct recipient
+      {
+	std::string address;
+	uint64_t amount;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(amount)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct transfer_description
+      {
+	uint64_t amount_in;
+	uint64_t amount_out;
+	uint32_t ring_size;
+	uint64_t unlock_time;
+	std::list<recipient> recipients;
+	std::string payment_id;
+	uint64_t change_amount;
+	std::string change_address;
+	uint64_t fee;
+	uint32_t dummy_outputs;
+	std::string extra;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(amount_in)
+	  KV_SERIALIZE(amount_out)
+	  KV_SERIALIZE(ring_size)
+	  KV_SERIALIZE(unlock_time)
+	  KV_SERIALIZE(recipients)
+	  KV_SERIALIZE(payment_id)
+	  KV_SERIALIZE(change_amount)
+	  KV_SERIALIZE(change_address)
+	  KV_SERIALIZE(fee)
+	  KV_SERIALIZE(dummy_outputs)
+	  KV_SERIALIZE(extra)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct txset_summary
+      {
+	uint64_t amount_in;
+	uint64_t amount_out;
+	std::list<recipient> recipients;
+	uint64_t change_amount;
+	std::string change_address;
+	uint64_t fee;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(amount_in)
+	  KV_SERIALIZE(amount_out)
+	  KV_SERIALIZE(recipients)
+	  KV_SERIALIZE(change_amount)
+	  KV_SERIALIZE(change_address)
+	  KV_SERIALIZE(fee)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct request_t
+      {
+	std::string unsigned_txset;
+	std::string multisig_txset;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(unsigned_txset)
+	  KV_SERIALIZE(multisig_txset)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<transfer_description> desc;
+	struct txset_summary summary;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(summary)
+	  KV_SERIALIZE(desc)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SIGN_TRANSFER
+    {
+      struct request_t
+      {
+	std::string unsigned_txset;
+	bool export_raw;
+	bool get_tx_keys;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(unsigned_txset)
+	  KV_SERIALIZE_OPT(export_raw, false)
+	  KV_SERIALIZE_OPT(get_tx_keys, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string signed_txset;
+	std::list<std::string> tx_hash_list;
+	std::list<std::string> tx_raw_list;
+	std::list<std::string> tx_key_list;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(signed_txset)
+	  KV_SERIALIZE(tx_hash_list)
+	  KV_SERIALIZE(tx_raw_list)
+	  KV_SERIALIZE(tx_key_list)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SUBMIT_TRANSFER
+    {
+      struct request_t
+      {
+	std::string tx_data_hex;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_data_hex)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<std::string> tx_hash_list;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_hash_list)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SWEEP_DUST
+    {
+      struct request_t
+      {
+	bool get_tx_keys;
+	bool do_not_relay;
+	bool get_tx_hex;
+	bool get_tx_metadata;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(get_tx_keys)
+	  KV_SERIALIZE_OPT(do_not_relay, false)
+	  KV_SERIALIZE_OPT(get_tx_hex, false)
+	  KV_SERIALIZE_OPT(get_tx_metadata, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      typedef split_transfer_response response_t;
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SWEEP_ALL
+    {
+      struct request_t
+      {
+	std::string address;
+	uint32_t account_index;
+	std::set<uint32_t> subaddr_indices;
+	bool subaddr_indices_all;
+	uint32_t priority;
+	uint64_t ring_size;
+	uint64_t outputs;
+	uint64_t unlock_time;
+	std::string payment_id;
+	bool get_tx_keys;
+	uint64_t below_amount;
+	bool do_not_relay;
+	bool get_tx_hex;
+	bool get_tx_metadata;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(subaddr_indices)
+	  KV_SERIALIZE_OPT(subaddr_indices_all, false)
+	  KV_SERIALIZE(priority)
+	  KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
+	  KV_SERIALIZE_OPT(outputs, (uint64_t)1)
+	  KV_SERIALIZE(unlock_time)
+	  KV_SERIALIZE(payment_id)
+	  KV_SERIALIZE(get_tx_keys)
+	  KV_SERIALIZE(below_amount)
+	  KV_SERIALIZE_OPT(do_not_relay, false)
+	  KV_SERIALIZE_OPT(get_tx_hex, false)
+	  KV_SERIALIZE_OPT(get_tx_metadata, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      typedef split_transfer_response response_t;
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SWEEP_SINGLE
+    {
+      struct request_t
+      {
+	std::string address;
+	uint32_t priority;
+	uint64_t ring_size;
+	uint64_t outputs;
+	uint64_t unlock_time;
+	std::string payment_id;
+	bool get_tx_key;
+	std::string key_image;
+	bool do_not_relay;
+	bool get_tx_hex;
+	bool get_tx_metadata;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(priority)
+	  KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
+	  KV_SERIALIZE_OPT(outputs, (uint64_t)1)
+	  KV_SERIALIZE(unlock_time)
+	  KV_SERIALIZE(payment_id)
+	  KV_SERIALIZE(get_tx_key)
+	  KV_SERIALIZE(key_image)
+	  KV_SERIALIZE_OPT(do_not_relay, false)
+	  KV_SERIALIZE_OPT(get_tx_hex, false)
+	  KV_SERIALIZE_OPT(get_tx_metadata, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      typedef single_transfer_response response_t;
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_RELAY_TX
+    {
+      struct request_t
+      {
+	std::string hex;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(hex)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string tx_hash;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_hash)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_STORE
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  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 payment_details
+    {
+      std::string payment_id;
+      std::string tx_hash;
+      uint64_t amount;
+      uint64_t block_height;
+      uint64_t unlock_time;
+      bool locked;
+      cryptonote::subaddress_index subaddr_index;
+      std::string address;
+
+      BEGIN_KV_SERIALIZE_MAP()
+	KV_SERIALIZE(payment_id)
+	KV_SERIALIZE(tx_hash)
+	KV_SERIALIZE(amount)
+	KV_SERIALIZE(block_height)
+	KV_SERIALIZE(unlock_time)
+	KV_SERIALIZE(locked)
+	KV_SERIALIZE(subaddr_index)
+	KV_SERIALIZE(address)
+	END_KV_SERIALIZE_MAP()
+    };
+
+    struct COMMAND_RPC_GET_PAYMENTS
+    {
+      struct request_t
+      {
+	std::string payment_id;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(payment_id)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<payment_details> payments;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(payments)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_BULK_PAYMENTS
+    {
+      struct request_t
+      {
+	std::vector<std::string> payment_ids;
+	uint64_t min_block_height;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(payment_ids)
+	  KV_SERIALIZE(min_block_height)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<payment_details> payments;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(payments)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct transfer_details
+    {
+      uint64_t amount;
+      bool spent;
+      uint64_t global_index;
+      std::string tx_hash;
+      cryptonote::subaddress_index subaddr_index;
+      std::string key_image;
+      std::string pubkey; // owned output public key found
+      uint64_t block_height;
+      bool frozen;
+      bool unlocked;
+
+      BEGIN_KV_SERIALIZE_MAP()
+	KV_SERIALIZE(amount)
+	KV_SERIALIZE(spent)
+	KV_SERIALIZE(global_index)
+	KV_SERIALIZE(tx_hash)
+	KV_SERIALIZE(subaddr_index)
+	KV_SERIALIZE(key_image)
+	KV_SERIALIZE(pubkey)
+	KV_SERIALIZE(block_height)
+	KV_SERIALIZE(frozen)
+	KV_SERIALIZE(unlocked)
+	END_KV_SERIALIZE_MAP()
+    };
+
+    struct COMMAND_RPC_INCOMING_TRANSFERS
+    {
+      struct request_t
+      {
+	std::string transfer_type;
+	uint32_t account_index;
+	std::set<uint32_t> subaddr_indices;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(transfer_type)
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(subaddr_indices)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<transfer_details> transfers;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(transfers)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    //JSON RPC V2
+    struct COMMAND_RPC_QUERY_KEY
+    {
+      struct request_t
+      {
+	std::string key_type;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(key_type)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string key;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(key)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_MAKE_INTEGRATED_ADDRESS
+    {
+      struct request_t
+      {
+	std::string standard_address;
+	std::string payment_id;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(standard_address)
+	  KV_SERIALIZE(payment_id)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string integrated_address;
+	std::string payment_id;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(integrated_address)
+	  KV_SERIALIZE(payment_id)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS
+    {
+      struct request_t
+      {
+	std::string integrated_address;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(integrated_address)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string standard_address;
+	std::string payment_id;
+	bool is_subaddress;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(standard_address)
+	  KV_SERIALIZE(payment_id)
+	  KV_SERIALIZE(is_subaddress)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_STOP_WALLET
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  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_RESCAN_BLOCKCHAIN
+    {
+      struct request_t
+      {
+	bool hard;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(hard, false)
+	  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_SET_TX_NOTES
+    {
+      struct request_t
+      {
+	std::list<std::string> txids;
+	std::list<std::string> notes;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txids)
+	  KV_SERIALIZE(notes)
+	  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_GET_TX_NOTES
+    {
+      struct request_t
+      {
+	std::list<std::string> txids;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txids)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<std::string> notes;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(notes)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SET_ATTRIBUTE
+    {
+      struct request_t
+      {
+	std::string key;
+	std::string value;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(key)
+	  KV_SERIALIZE(value)
+	  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_GET_ATTRIBUTE
+    {
+      struct request_t
+      {
+
+	std::string key;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(key)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string value;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(value)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_TX_KEY
+    {
+      struct request_t
+      {
+	std::string txid;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string tx_key;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_key)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_CHECK_TX_KEY
+    {
+      struct request_t
+      {
+	std::string txid;
+	std::string tx_key;
+	std::string address;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  KV_SERIALIZE(tx_key)
+	  KV_SERIALIZE(address)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t received;
+	bool in_pool;
+	uint64_t confirmations;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(received)
+	  KV_SERIALIZE(in_pool)
+	  KV_SERIALIZE(confirmations)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_TX_PROOF
+    {
+      struct request_t
+      {
+	std::string txid;
+	std::string address;
+	std::string message;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(message)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_CHECK_TX_PROOF
+    {
+      struct request_t
+      {
+	std::string txid;
+	std::string address;
+	std::string message;
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(message)
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	bool good;
+	uint64_t received;
+	bool in_pool;
+	uint64_t confirmations;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(good)
+	  KV_SERIALIZE(received)
+	  KV_SERIALIZE(in_pool)
+	  KV_SERIALIZE(confirmations)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    typedef std::vector<uint64_t> amounts_container;
+    struct transfer_entry
+    {
+      std::string txid;
+      std::string payment_id;
+      uint64_t height;
+      uint64_t timestamp;
+      uint64_t amount;
+      amounts_container amounts;
+      uint64_t fee;
+      std::string note;
+      std::list<transfer_destination> destinations;
+      std::string type;
+      uint64_t unlock_time;
+      bool locked;
+      cryptonote::subaddress_index subaddr_index;
+      std::vector<cryptonote::subaddress_index> subaddr_indices;
+      std::string address;
+      bool double_spend_seen;
+      uint64_t confirmations;
+      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(unlock_time)
+	KV_SERIALIZE(locked)
+	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)
+	END_KV_SERIALIZE_MAP()
+    };
+
+    struct COMMAND_RPC_GET_SPEND_PROOF
+    {
+      struct request_t
+      {
+	std::string txid;
+	std::string message;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  KV_SERIALIZE(message)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_CHECK_SPEND_PROOF
+    {
+      struct request_t
+      {
+	std::string txid;
+	std::string message;
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  KV_SERIALIZE(message)
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	bool good;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(good)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_RESERVE_PROOF
+    {
+      struct request_t
+      {
+	bool all;
+	uint32_t account_index;     // ignored when `all` is true
+	uint64_t amount;            // ignored when `all` is true
+	std::string message;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(all)
+	  KV_SERIALIZE(account_index)
+	  KV_SERIALIZE(amount)
+	  KV_SERIALIZE(message)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_CHECK_RESERVE_PROOF
+    {
+      struct request_t
+      {
+	std::string address;
+	std::string message;
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(message)
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	bool good;
+	uint64_t total;
+	uint64_t spent;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(good)
+	  KV_SERIALIZE(total)
+	  KV_SERIALIZE(spent)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_TRANSFERS
+    {
+      struct request_t
+      {
+	bool in;
+	bool out;
+	bool pending;
+	bool failed;
+	bool pool;
+
+	bool filter_by_height;
+	uint64_t min_height;
+	uint64_t max_height;
+	uint32_t account_index;
+	std::set<uint32_t> subaddr_indices;
+	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)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<transfer_entry> in;
+	std::list<transfer_entry> out;
+	std::list<transfer_entry> pending;
+	std::list<transfer_entry> failed;
+	std::list<transfer_entry> pool;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  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;
+    };
+
+    struct COMMAND_RPC_GET_TRANSFER_BY_TXID
+    {
+      struct request_t
+      {
+	std::string txid;
+	uint32_t account_index;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txid)
+	  KV_SERIALIZE_OPT(account_index, (uint32_t)0)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	transfer_entry transfer;
+	std::list<transfer_entry> transfers;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(transfer)
+	  KV_SERIALIZE(transfers)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SIGN
+    {
+      struct request_t
+      {
+	std::string data;
+	uint32_t account_index;
+	uint32_t address_index;
+	std::string signature_type;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(data)
+	  KV_SERIALIZE_OPT(account_index, 0u)
+	  KV_SERIALIZE_OPT(address_index, 0u)
+	  KV_SERIALIZE(signature_type)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_VERIFY
+    {
+      struct request_t
+      {
+	std::string data;
+	std::string address;
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(data)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	bool good;
+	unsigned version;
+	bool old;
+	std::string signature_type;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  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;
+    };
+
+    struct COMMAND_RPC_EXPORT_OUTPUTS
+    {
+      struct request_t
+      {
+	bool all;
+	uint32_t start;
+	uint32_t count;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(all)
+	  KV_SERIALIZE_OPT(start, 0u)
+	  KV_SERIALIZE_OPT(count, 0xffffffffu)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string outputs_data_hex;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(outputs_data_hex)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_IMPORT_OUTPUTS
+    {
+      struct request_t
+      {
+	std::string outputs_data_hex;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(outputs_data_hex)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t num_imported;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(num_imported)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_EXPORT_KEY_IMAGES
+    {
+      struct request_t
+      {
+	bool all;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(all, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct signed_key_image
+      {
+	std::string key_image;
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(key_image)
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response_t
+      {
+	uint32_t offset;
+	std::vector<signed_key_image> signed_key_images;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(offset)
+	  KV_SERIALIZE(signed_key_images)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_IMPORT_KEY_IMAGES
+    {
+      struct signed_key_image
+      {
+	std::string key_image;
+	std::string signature;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(key_image)
+	  KV_SERIALIZE(signature)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct request_t
+      {
+	uint32_t offset;
+	std::vector<signed_key_image> signed_key_images;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  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;
+
+      struct response_t
+      {
+	uint64_t height;
+	uint64_t spent;
+	uint64_t unspent;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(height)
+	  KV_SERIALIZE(spent)
+	  KV_SERIALIZE(unspent)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+    struct COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES
+    {
+      struct request_t
+      {
+	bool all;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(all, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint32_t offset;
+	std::string encrypted_key_images_blob;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(offset)
+	  KV_SERIALIZE(encrypted_key_images_blob)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES
+    {
+      struct request_t
+      {
+	uint32_t offset;
+	std::string encrypted_key_images_blob;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(offset, (uint32_t)0)
+	  KV_SERIALIZE(encrypted_key_images_blob)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t height;
+	uint64_t spent;
+	uint64_t unspent;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(height)
+	  KV_SERIALIZE(spent)
+	  KV_SERIALIZE(unspent)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct uri_spec
+    {
+      std::string address;
+      std::string payment_id;
+      uint64_t amount;
+      std::string tx_description;
+      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)
+	END_KV_SERIALIZE_MAP()
+    };
+
+    struct COMMAND_RPC_MAKE_URI
+    {
+      struct request_t: public uri_spec
+      {
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string uri;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(uri)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_PARSE_URI
+    {
+      struct request_t
+      {
+	std::string uri;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(uri)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uri_spec uri;
+	std::vector<std::string> unknown_parameters;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(uri)
+	  KV_SERIALIZE(unknown_parameters)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_ADD_ADDRESS_BOOK_ENTRY
+    {
+      struct request_t
+      {
+	std::string address;
+	std::string description;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(description)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t index;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(index)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_EDIT_ADDRESS_BOOK_ENTRY
+    {
+      struct request_t
+      {
+	uint64_t index;
+	bool set_address;
+	std::string address;
+	bool set_description;
+	std::string description;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(index)
+	  KV_SERIALIZE(set_address)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(set_description)
+	  KV_SERIALIZE(description)
+	  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_GET_ADDRESS_BOOK_ENTRY
+    {
+      struct request_t
+      {
+	std::list<uint64_t> entries;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(entries)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct entry
+      {
+	uint64_t index;
+	std::string address;
+	std::string description;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(index)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(description)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response_t
+      {
+	std::vector<entry> entries;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(entries)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_DELETE_ADDRESS_BOOK_ENTRY
+    {
+      struct request_t
+      {
+	uint64_t index;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(index)
+	  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_RESCAN_SPENT
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  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_REFRESH
+    {
+      struct request_t
+      {
+	uint64_t start_height;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(start_height, (uint64_t) 0)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t blocks_fetched;
+	bool received_money;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(blocks_fetched)
+	  KV_SERIALIZE(received_money)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_AUTO_REFRESH
+    {
+      struct request_t
+      {
+	bool enable;
+	uint32_t period; // seconds
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(enable, true)
+	  KV_SERIALIZE_OPT(period, (uint32_t)0)
+	  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_SCAN_TX
+    {
+      struct request_t
+      {
+	std::list<std::string> txids;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(txids)
+	  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_START_MINING
+    {
+      struct request_t
+      {
+	uint64_t    threads_count;
+	bool        do_background_mining;
+	bool        ignore_battery;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(threads_count)
+	  KV_SERIALIZE(do_background_mining)        
+	  KV_SERIALIZE(ignore_battery)        
+	  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_STOP_MINING
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  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_GET_LANGUAGES
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::vector<std::string> languages;
+	std::vector<std::string> languages_local;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(languages)
+	  KV_SERIALIZE(languages_local)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_CREATE_WALLET
+    {
+      struct request_t
+      {
+	std::string filename;
+	std::string password;
+	std::string language;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(filename)
+	  KV_SERIALIZE(password)
+	  KV_SERIALIZE(language)
+	  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_OPEN_WALLET
+    {
+      struct request_t
+      {
+	std::string filename;
+	std::string password;
+	bool autosave_current;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(filename)
+	  KV_SERIALIZE(password)
+	  KV_SERIALIZE_OPT(autosave_current, true)
+	  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_CLOSE_WALLET
+    {
+      struct request_t
+      {
+	bool autosave_current;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(autosave_current, true)
+	  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_CHANGE_WALLET_PASSWORD
+    {
+      struct request_t
+      {
+	std::string old_password;
+	std::string new_password;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(old_password)
+	  KV_SERIALIZE(new_password)
+	  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_GENERATE_FROM_KEYS
+    {
+      struct request
+      {
+	uint64_t restore_height;
+	std::string filename;
+	std::string address;
+	std::string spendkey;
+	std::string viewkey;
+	std::string password;
+	bool autosave_current;
+	std::string language;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
+	  KV_SERIALIZE(filename)
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(spendkey)
+	  KV_SERIALIZE(viewkey)
+	  KV_SERIALIZE(password)
+	  KV_SERIALIZE_OPT(autosave_current, true)
+	  KV_SERIALIZE(language)
+	  END_KV_SERIALIZE_MAP()
+      };
+
+      struct response
+      {
+	std::string address;
+	std::string info;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(info)
+	  END_KV_SERIALIZE_MAP()
+      };
+    };
+
+    struct COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET
+    {
+      struct request_t
+      {
+	uint64_t restore_height;
+	std::string filename;
+	std::string seed;
+	std::string seed_offset;
+	std::string password;
+	std::string language;
+	bool autosave_current;
+	bool enable_multisig_experimental;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
+	  KV_SERIALIZE(filename)
+	  KV_SERIALIZE(seed)
+	  KV_SERIALIZE(seed_offset)
+	  KV_SERIALIZE(password)
+	  KV_SERIALIZE(language)
+	  KV_SERIALIZE_OPT(autosave_current, true)
+	  KV_SERIALIZE_OPT(enable_multisig_experimental, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string address;
+	std::string seed;
+	std::string info;
+	bool was_deprecated;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(seed)
+	  KV_SERIALIZE(info)
+	  KV_SERIALIZE(was_deprecated)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_IS_MULTISIG
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	bool multisig;
+	bool kex_is_done;
+	bool ready;
+	uint32_t threshold;
+	uint32_t total;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(multisig)
+	  KV_SERIALIZE(kex_is_done)
+	  KV_SERIALIZE(ready)
+	  KV_SERIALIZE(threshold)
+	  KV_SERIALIZE(total)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_PREPARE_MULTISIG
+    {
+      struct request_t
+      {
+	bool enable_multisig_experimental;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE_OPT(enable_multisig_experimental, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string multisig_info;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(multisig_info)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_MAKE_MULTISIG
+    {
+      struct request_t
+      {
+	std::vector<std::string> multisig_info;
+	uint32_t threshold;
+	std::string password;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(multisig_info)
+	  KV_SERIALIZE(threshold)
+	  KV_SERIALIZE(password)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string address;
+	std::string multisig_info;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(multisig_info)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_EXPORT_MULTISIG
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string info;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(info)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_IMPORT_MULTISIG
+    {
+      struct request_t
+      {
+	std::vector<std::string> info;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(info)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t n_outputs;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(n_outputs)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_FINALIZE_MULTISIG
+    {
+      // NOP
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  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_EXCHANGE_MULTISIG_KEYS
+    {
+      struct request_t
+      {
+	std::string password;
+	std::vector<std::string> multisig_info;
+	bool force_update_use_with_caution;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(password)
+	  KV_SERIALIZE(multisig_info)
+	  KV_SERIALIZE_OPT(force_update_use_with_caution, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string address;
+	std::string multisig_info;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(multisig_info)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SIGN_MULTISIG
+    {
+      struct request_t
+      {
+	std::string tx_data_hex;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_data_hex)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string tx_data_hex;
+	std::list<std::string> tx_hash_list;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_data_hex)
+	  KV_SERIALIZE(tx_hash_list)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SUBMIT_MULTISIG
+    {
+      struct request_t
+      {
+	std::string tx_data_hex;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_data_hex)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::list<std::string> tx_hash_list;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(tx_hash_list)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_GET_VERSION
+    {
+      struct request_t
+      {
+	BEGIN_KV_SERIALIZE_MAP()
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint32_t version;
+	bool release;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(version)
+	  KV_SERIALIZE(release)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_VALIDATE_ADDRESS
+    {
+      struct request_t
+      {
+	std::string address;
+	bool any_net_type;
+	bool allow_openalias;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE_OPT(any_net_type, false)
+	  KV_SERIALIZE_OPT(allow_openalias, false)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	bool valid;
+	bool integrated;
+	bool subaddress;
+	std::string nettype;
+	std::string openalias_address;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(valid)
+	  KV_SERIALIZE(integrated)
+	  KV_SERIALIZE(subaddress)
+	  KV_SERIALIZE(nettype)
+	  KV_SERIALIZE(openalias_address)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_SET_DAEMON
+    {
+      struct request_t
+      {
+	std::string address;
+	std::string username;
+	std::string password;
+	bool trusted;
+	std::string ssl_support; // disabled, enabled, autodetect
+	std::string ssl_private_key_path;
+	std::string ssl_certificate_path;
+	std::string ssl_ca_file;
+	std::vector<std::string> ssl_allowed_fingerprints;
+	bool ssl_allow_any_cert;
+	std::string proxy;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(address)
+	  KV_SERIALIZE(username)
+	  KV_SERIALIZE(password)
+	  KV_SERIALIZE_OPT(trusted, false)
+	  KV_SERIALIZE_OPT(ssl_support, (std::string)"autodetect")
+	  KV_SERIALIZE(ssl_private_key_path)
+	  KV_SERIALIZE(ssl_certificate_path)
+	  KV_SERIALIZE(ssl_ca_file)
+	  KV_SERIALIZE(ssl_allowed_fingerprints)
+	  KV_SERIALIZE_OPT(ssl_allow_any_cert, false)
+	  KV_SERIALIZE_OPT(proxy, (std::string)"")
+	  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_SET_LOG_LEVEL
+    {
+      struct request_t
+      {
+	int8_t level;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(level)
+	  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_SET_LOG_CATEGORIES
+    {
+      struct request_t
+      {
+	std::string categories;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(categories)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	std::string categories;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(categories)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+    struct COMMAND_RPC_ESTIMATE_TX_SIZE_AND_WEIGHT
+    {
+      struct request_t
+      {
+	uint32_t n_inputs;
+	uint32_t n_outputs;
+	uint32_t ring_size;
+	bool rct;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(n_inputs)
+	  KV_SERIALIZE(n_outputs)
+	  KV_SERIALIZE_OPT(ring_size, 0u)
+	  KV_SERIALIZE_OPT(rct, true)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<request_t> request;
+
+      struct response_t
+      {
+	uint64_t size;
+	uint64_t weight;
+
+	BEGIN_KV_SERIALIZE_MAP()
+	  KV_SERIALIZE(size)
+	  KV_SERIALIZE(weight)
+	  END_KV_SERIALIZE_MAP()
+      };
+      typedef epee::misc_utils::struct_init<response_t> response;
+    };
+
+  }
 }

From 54dab2e1219412ce631f5d7f46bcad94b7a180cd Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 15:36:57 -0600
Subject: [PATCH 02/12] add magic

---
 src/wallet/wallet_rpc_server.cpp | 218 +++++++++++++++++++------------
 1 file changed, 134 insertions(+), 84 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 7de53371c..3de051376 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -56,6 +56,8 @@ using namespace epee;
 #include "rpc/core_rpc_server_commands_defs.h"
 #include "daemonizer/daemonizer.h"
 
+#define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\003"
+
 #undef MONERO_DEFAULT_LOG_CATEGORY
 #define MONERO_DEFAULT_LOG_CATEGORY "wallet.rpc"
 
@@ -2951,102 +2953,150 @@ namespace tools
 
     return true;
   }
-  //------------------------------------------------------------------------------------------------------------------------------
-  bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+  /bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+{
+  if (!m_wallet) return not_open(er);
+  try
   {
-    if (!m_wallet) return not_open(er);
+    std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
+    res.offset = ski.first;
+
+    std::string data;
+    const cryptonote::account_public_address &keys = m_wallet->get_account().get_keys().m_account_address;
+    
+    data.reserve(4 + sizeof(crypto::public_key) * 2 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)));
+    
+    data.resize(4);
+    data[0] = res.offset & 0xff;
+    data[1] = (res.offset >> 8) & 0xff;
+    data[2] = (res.offset >> 16) & 0xff;
+    data[3] = (res.offset >> 24) & 0xff;
+
+    data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
+    data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
+
+    for (const auto &item : ski.second)
+    {
+      data += std::string((const char *)&item.first, sizeof(crypto::key_image));
+      data += std::string((const char *)&item.second, sizeof(crypto::signature));
+    }
+
+    std::string ciphertext = m_wallet->encrypt_with_view_secret_key(data);
+
+    std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
+    res.encrypted_key_images_blob = epee::string_tools::buff_to_hex_nodelimer(magic + ciphertext);
+  }
+  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_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+{
+  if (!m_wallet) return not_open(er);
+  if (m_restricted)
+  {
+    er.code = WALLET_RPC_ERROR_CODE_DENIED;
+    er.message = "Command unavailable in restricted mode.";
+    return false;
+  }
+  if (!m_wallet->is_trusted_daemon())
+  {
+    er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+    er.message = "This command requires a trusted daemon.";
+    return false;
+  }
+  try
+  {
+    std::string data;
+    if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, data))
+    {
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Failed to parse encrypted key images blob";
+      return false;
+    }
+
+    const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
+    if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
+    {
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Bad key image export file magic in blob";
+      return false;
+    }
+
     try
     {
-      std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
-      res.offset = ski.first;
-
-      // Serialize the key images and signatures into a single blob
-      std::string data;
-      data.reserve(ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)));
-      for (const auto &item : ski.second)
-      {
-	data += std::string((const char *)&item.first, sizeof(crypto::key_image));
-	data += std::string((const char *)&item.second, sizeof(crypto::signature));
-      }
-
-      // Encrypt the serialized data
-      std::string ciphertext = m_wallet->encrypt_with_view_secret_key(data);
-
-      // Encode the encrypted data as hex
-      res.encrypted_key_images_blob = epee::string_tools::buff_to_hex_nodelimer(ciphertext);
+      data = m_wallet->decrypt_with_view_secret_key(std::string(data, magiclen));
     }
     catch (const std::exception& e)
     {
-      handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Failed to decrypt blob";
       return false;
     }
 
-    return true;
+    const size_t headerlen = 4 + 2 * sizeof(crypto::public_key);
+    if (data.size() < headerlen)
+    {
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Bad data size from file";
+      return false;
+    }
+
+    uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24);
+    if (offset > m_wallet->get_num_transfer_details())
+    {
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Offset larger than known outputs";
+      return false;
+    }
+
+    const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4];
+    const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)];
+    const cryptonote::account_public_address &keys = m_wallet->get_account().get_keys().m_account_address;
+    if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
+    {
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Key images from different account";
+      return false;
+    }
+
+    const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
+    if ((data.size() - headerlen) % record_size)
+    {
+      er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
+      er.message = "Bad data size from file";
+      return false;
+    }
+    size_t nki = (data.size() - headerlen) / record_size;
+
+    std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
+    ski.reserve(nki);
+    for (size_t n = 0; n < nki; ++n)
+    {
+      crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data[headerlen + n * record_size]);
+      crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data[headerlen + n * record_size + sizeof(crypto::key_image)]);
+
+      ski.push_back(std::make_pair(key_image, signature));
+    }
+    
+    uint64_t spent = 0, unspent = 0;
+    uint64_t height = m_wallet->import_key_images(ski, offset, spent, unspent);
+    res.height = height;
+    res.spent = spent;
+    res.unspent = unspent;
   }
-  //------------------------------------------------------------------------------------------------------------------------------
-  bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+  catch (const std::exception& e)
   {
-    if (!m_wallet) return not_open(er);
-    if (m_restricted)
-    {
-      er.code = WALLET_RPC_ERROR_CODE_DENIED;
-      er.message = "Command unavailable in restricted mode.";
-      return false;
-    }
-    if (!m_wallet->is_trusted_daemon())
-    {
-      er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
-      er.message = "This command requires a trusted daemon.";
-      return false;
-    }
-    try
-    {
-      // Decode the hex-encoded encrypted blob
-      std::string ciphertext;
-      if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, ciphertext))
-      {
-	er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
-	er.message = "Failed to parse encrypted key images blob";
-	return false;
-      }
-
-      // Decrypt the ciphertext
-      std::string decrypted_data = m_wallet->decrypt_with_view_secret_key(ciphertext);
-
-      // Deserialize the decrypted data into key images and signatures
-      std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
-      const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
-      if (decrypted_data.size() % record_size != 0)
-      {
-	er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
-	er.message = "Decrypted data size is not a multiple of the record size";
-	return false;
-      }
-      size_t num_records = decrypted_data.size() / record_size;
-      ski.reserve(num_records);
-      for (size_t i = 0; i < num_records; ++i)
-      {
-	crypto::key_image ki;
-	crypto::signature sig;
-	memcpy(&ki, &decrypted_data[i * record_size], sizeof(crypto::key_image));
-	memcpy(&sig, &decrypted_data[i * record_size + sizeof(crypto::key_image)], sizeof(crypto::signature));
-	ski.emplace_back(ki, sig);
-      }
-
-      uint64_t spent = 0, unspent = 0;
-      uint64_t height = m_wallet->import_key_images(ski, req.offset, spent, unspent);
-      res.height = height;
-      res.spent = spent;
-      res.unspent = unspent;
-    }
-    catch (const std::exception& e)
-    {
-      handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
-      return false;
-    }
-
-    return true;
+    handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+    return false;
   }
+
+  return true;
+}/------------------------------------------------------------------------------------------------------------------------------
   //------------------------------------------------------------------------------------------------------------------------------
   bool wallet_rpc_server::on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er, const connection_context *ctx)
   {

From 86ba8e2776713fe1a1dd9e1e5ff1facfb1e8d5c3 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 15:48:20 -0600
Subject: [PATCH 03/12] fix /

---
 src/wallet/wallet_rpc_server.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 3de051376..1db55d85f 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -2993,8 +2993,9 @@ namespace tools
   }
 
   return true;
-}/------------------------------------------------------------------------------------------------------------------------------
-  /bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+}
+//------------------------------------------------------------------------------------------------------------------------------
+bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
 {
   if (!m_wallet) return not_open(er);
   if (m_restricted)
@@ -3096,7 +3097,7 @@ namespace tools
   }
 
   return true;
-}/------------------------------------------------------------------------------------------------------------------------------
+}
   //------------------------------------------------------------------------------------------------------------------------------
   bool wallet_rpc_server::on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er, const connection_context *ctx)
   {

From 9b6499ccaf914efab073d9080d114d99f91780a2 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 15:50:35 -0600
Subject: [PATCH 04/12] fix /

---
 src/wallet/wallet_rpc_server.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 1db55d85f..7976cb7af 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -2953,7 +2953,8 @@ namespace tools
 
     return true;
   }
-  /bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
+  //------------------------------------------------------------------------------------------------------------------------------
+  bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
 {
   if (!m_wallet) return not_open(er);
   try

From d2e3cff9f5ea82dc2998afae05e94c28282c4395 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 17:28:04 -0600
Subject: [PATCH 05/12] change to hex_to_pod

---
 src/wallet/wallet_rpc_server.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 7976cb7af..7251beb4a 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3014,7 +3014,7 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
   try
   {
     std::string data;
-    if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, data))
+    if (!epee::string_tools::hex_to_pod(req.encrypted_key_images_blob, data))
     {
       er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
       er.message = "Failed to parse encrypted key images blob";

From 5722f42423644122602e7166f61585783f1d3ad6 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 17:51:10 -0600
Subject: [PATCH 06/12] change back and add debug code

---
 src/wallet/wallet_rpc_server.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 7251beb4a..d8e3c778e 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3014,14 +3014,24 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
   try
   {
     std::string data;
-    if (!epee::string_tools::hex_to_pod(req.encrypted_key_images_blob, data))
+    if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, data))
     {
       er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
       er.message = "Failed to parse encrypted key images blob";
       return false;
     }
 
+
+    // Debug: Print the first few bytes of the decoded data
+    std::cout << "First 32 bytes of decoded data: ";
+    for (size_t i = 0; i < std::min(data.size(), size_t(32)); ++i) {
+      std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)(unsigned char)data[i];
+    }
+    std::cout << std::endl;
+
     const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
+    std::cout << "Magic length: " << magiclen << std::endl;
+    std::cout << "Expected magic: ";
     if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
     {
       er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;

From 67e634e734980cd02590bde4295729fe6c892274 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 18:35:15 -0600
Subject: [PATCH 07/12] more debug code

---
 src/wallet/wallet_rpc_server.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index d8e3c778e..f04a14547 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3022,6 +3022,8 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
     }
 
 
+    std::out << "encrypted_key_images_blob: " << req.encrypted_key_images_blob;
+    std::out << "data: " << data;
     // Debug: Print the first few bytes of the decoded data
     std::cout << "First 32 bytes of decoded data: ";
     for (size_t i = 0; i < std::min(data.size(), size_t(32)); ++i) {

From 26913952a60a510ba3bfdc8f83e555687ad62a26 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 18:38:54 -0600
Subject: [PATCH 08/12] more debug code

---
 src/wallet/wallet_rpc_server.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index f04a14547..fd2b82383 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3022,8 +3022,8 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
     }
 
 
-    std::out << "encrypted_key_images_blob: " << req.encrypted_key_images_blob;
-    std::out << "data: " << data;
+    std::cout << "encrypted_key_images_blob: " << req.encrypted_key_images_blob;
+    std::cout << "data: " << data;
     // Debug: Print the first few bytes of the decoded data
     std::cout << "First 32 bytes of decoded data: ";
     for (size_t i = 0; i < std::min(data.size(), size_t(32)); ++i) {

From c5822d77ce232906da5c89cb5a97830e17d70bc8 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 19:02:08 -0600
Subject: [PATCH 09/12] more debug code

---
 src/wallet/wallet_rpc_server.cpp             | 4 ++--
 src/wallet/wallet_rpc_server_commands_defs.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index fd2b82383..5c553aa71 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3022,8 +3022,8 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
     }
 
 
-    std::cout << "encrypted_key_images_blob: " << req.encrypted_key_images_blob;
-    std::cout << "data: " << data;
+    std::cout << "encrypted_key_images_blob: " << req.encrypted_key_images_blob << std::endl;
+    std::cout << "data: " << data << std::endl;
     // Debug: Print the first few bytes of the decoded data
     std::cout << "First 32 bytes of decoded data: ";
     for (size_t i = 0; i < std::min(data.size(), size_t(32)); ++i) {
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 42b43a26b..85866307f 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -1858,7 +1858,7 @@ namespace tools
 
 	BEGIN_KV_SERIALIZE_MAP()
 	  KV_SERIALIZE_OPT(offset, (uint32_t)0)
-	  KV_SERIALIZE(encrypted_key_images_blob)
+	  KV_SERIALIZE_OPT(encrypted_key_images_blob, "WTF")
 	  END_KV_SERIALIZE_MAP()
       };
       typedef epee::misc_utils::struct_init<request_t> request;

From 75c14c8b4589f9d919624b14a43c34d0c604ed85 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Thu, 18 Jul 2024 21:18:56 -0600
Subject: [PATCH 10/12] final modifications to adding endpoints
 import_encrypted_key_images and export_encrypted_key_images

---
 src/wallet/wallet_rpc_server.cpp             | 12 ------------
 src/wallet/wallet_rpc_server_commands_defs.h |  2 +-
 2 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 5c553aa71..7976cb7af 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3021,19 +3021,7 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
       return false;
     }
 
-
-    std::cout << "encrypted_key_images_blob: " << req.encrypted_key_images_blob << std::endl;
-    std::cout << "data: " << data << std::endl;
-    // Debug: Print the first few bytes of the decoded data
-    std::cout << "First 32 bytes of decoded data: ";
-    for (size_t i = 0; i < std::min(data.size(), size_t(32)); ++i) {
-      std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)(unsigned char)data[i];
-    }
-    std::cout << std::endl;
-
     const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
-    std::cout << "Magic length: " << magiclen << std::endl;
-    std::cout << "Expected magic: ";
     if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
     {
       er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 85866307f..42b43a26b 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -1858,7 +1858,7 @@ namespace tools
 
 	BEGIN_KV_SERIALIZE_MAP()
 	  KV_SERIALIZE_OPT(offset, (uint32_t)0)
-	  KV_SERIALIZE_OPT(encrypted_key_images_blob, "WTF")
+	  KV_SERIALIZE(encrypted_key_images_blob)
 	  END_KV_SERIALIZE_MAP()
       };
       typedef epee::misc_utils::struct_init<request_t> request;

From 5e7c23446205145da9ad5a78585d4a60f1251788 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Tue, 20 Aug 2024 22:16:05 -0600
Subject: [PATCH 11/12] .gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 9f62575e5..4387e1c9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -120,3 +120,5 @@ nbproject
 __pycache__/
 *.pyc
 *.log
+.gitignore
+/dist/

From 25b09501e3c831d855bb01f1038a95e7d0ca48b2 Mon Sep 17 00:00:00 2001
From: who asks? <user@localhost>
Date: Tue, 20 Aug 2024 23:32:13 -0600
Subject: [PATCH 12/12] remove whitespace

---
 src/wallet/wallet_rpc_server.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 5dcc8e47d..e95ff1b05 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -3117,9 +3117,9 @@ namespace tools
 
     std::string data;
     const cryptonote::account_public_address &keys = m_wallet->get_account().get_keys().m_account_address;
-    
+
     data.reserve(4 + sizeof(crypto::public_key) * 2 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)));
-    
+
     data.resize(4);
     data[0] = res.offset & 0xff;
     data[1] = (res.offset >> 8) & 0xff;
@@ -3237,7 +3237,7 @@ bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND
 
       ski.push_back(std::make_pair(key_image, signature));
     }
-    
+
     uint64_t spent = 0, unspent = 0;
     uint64_t height = m_wallet->import_key_images(ski, offset, spent, unspent);
     res.height = height;