|
|
|
@ -34,6 +34,7 @@
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
#include <boost/archive/portable_binary_iarchive.hpp>
|
|
|
|
|
#include "cryptonote_core/cryptonote_basic.h"
|
|
|
|
|
#include "cryptonote_core/cryptonote_basic_impl.h"
|
|
|
|
|
#include "ringct/rctSigs.h"
|
|
|
|
@ -44,6 +45,7 @@
|
|
|
|
|
#include "serialization/variant.h"
|
|
|
|
|
#include "serialization/vector.h"
|
|
|
|
|
#include "serialization/binary_utils.h"
|
|
|
|
|
#include "wallet/wallet2.h"
|
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
@ -649,3 +651,514 @@ TEST(Serialization, serializes_ringct_types)
|
|
|
|
|
ASSERT_TRUE(serialization::dump_binary(tx1, blob2));
|
|
|
|
|
ASSERT_TRUE(blob == blob2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(Serialization, portability_wallet)
|
|
|
|
|
{
|
|
|
|
|
const bool testnet = true;
|
|
|
|
|
const bool restricted = false;
|
|
|
|
|
tools::wallet2 w(testnet, restricted);
|
|
|
|
|
string wallet_file = "../data/wallet_9svHk1";
|
|
|
|
|
string password = "test";
|
|
|
|
|
bool r = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
w.load(wallet_file, password);
|
|
|
|
|
r = true;
|
|
|
|
|
}
|
|
|
|
|
catch (const exception& e)
|
|
|
|
|
{}
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
/*
|
|
|
|
|
fields of tools::wallet2 to be checked:
|
|
|
|
|
std::vector<crypto::hash> m_blockchain
|
|
|
|
|
std::vector<transfer_details> m_transfers // TODO
|
|
|
|
|
cryptonote::account_public_address m_account_public_address
|
|
|
|
|
std::unordered_map<crypto::key_image, size_t> m_key_images
|
|
|
|
|
std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs
|
|
|
|
|
std::unordered_multimap<crypto::hash, payment_details> m_payments
|
|
|
|
|
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys
|
|
|
|
|
std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs
|
|
|
|
|
std::unordered_map<crypto::hash, std::string> m_tx_notes
|
|
|
|
|
std::unordered_map<crypto::hash, payment_details> m_unconfirmed_payments
|
|
|
|
|
std::unordered_map<crypto::public_key, size_t> m_pub_keys
|
|
|
|
|
std::vector<tools::wallet2::address_book_row> m_address_book
|
|
|
|
|
*/
|
|
|
|
|
// blockchain
|
|
|
|
|
ASSERT_TRUE(w.m_blockchain.size() == 1);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(w.m_blockchain[0]) == "48ca7cd3c8de5b6a4d53d2861fbdaedca141553559f9be9520068053cda8430b");
|
|
|
|
|
// transfers (TODO)
|
|
|
|
|
ASSERT_TRUE(w.m_transfers.size() == 3);
|
|
|
|
|
// account public address
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(w.m_account_public_address.m_view_public_key) == "e47d4b6df6ab7339539148c2a03ad3e2f3434e5ab2046848e1f21369a3937cad");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(w.m_account_public_address.m_spend_public_key) == "13daa2af00ad26a372d317195de0bdd716f7a05d33bc4d7aff1664b6ee93c060");
|
|
|
|
|
// key images
|
|
|
|
|
ASSERT_TRUE(w.m_key_images.size() == 3);
|
|
|
|
|
{
|
|
|
|
|
crypto::key_image ki[3];
|
|
|
|
|
epee::string_tools::hex_to_pod("c5680d3735b90871ca5e3d90cd82d6483eed1151b9ab75c2c8c3a7d89e00a5a8", ki[0]);
|
|
|
|
|
epee::string_tools::hex_to_pod("d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0", ki[1]);
|
|
|
|
|
epee::string_tools::hex_to_pod("6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76", ki[2]);
|
|
|
|
|
ASSERT_TRUE(w.m_key_images.find(ki[0])->second == 0);
|
|
|
|
|
ASSERT_TRUE(w.m_key_images.find(ki[1])->second == 1);
|
|
|
|
|
ASSERT_TRUE(w.m_key_images.find(ki[2])->second == 2);
|
|
|
|
|
}
|
|
|
|
|
// unconfirmed txs
|
|
|
|
|
ASSERT_TRUE(w.m_unconfirmed_txs.size() == 0);
|
|
|
|
|
// payments
|
|
|
|
|
ASSERT_TRUE(w.m_payments.size() == 2);
|
|
|
|
|
{
|
|
|
|
|
auto pd0 = w.m_payments.begin();
|
|
|
|
|
auto pd1 = pd0;
|
|
|
|
|
++pd1;
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(pd0->first) == "0000000000000000000000000000000000000000000000000000000000000000");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(pd1->first) == "0000000000000000000000000000000000000000000000000000000000000000");
|
|
|
|
|
if (epee::string_tools::pod_to_hex(pd0->second.m_tx_hash) == "ec34c9bb12b99af33d49691384eee5bed9171498ff04e59516505f35d1fc5efc")
|
|
|
|
|
swap(pd0, pd1);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(pd0->second.m_tx_hash) == "15024343b38e77a1a9860dfed29921fa17e833fec837191a6b04fa7cb9605b8e");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(pd1->second.m_tx_hash) == "ec34c9bb12b99af33d49691384eee5bed9171498ff04e59516505f35d1fc5efc");
|
|
|
|
|
ASSERT_TRUE(pd0->second.m_amount == 13400845012231);
|
|
|
|
|
ASSERT_TRUE(pd1->second.m_amount == 1200000000000);
|
|
|
|
|
ASSERT_TRUE(pd0->second.m_block_height == 818424);
|
|
|
|
|
ASSERT_TRUE(pd1->second.m_block_height == 818522);
|
|
|
|
|
ASSERT_TRUE(pd0->second.m_unlock_time == 818484);
|
|
|
|
|
ASSERT_TRUE(pd1->second.m_unlock_time == 0);
|
|
|
|
|
ASSERT_TRUE(pd0->second.m_timestamp == 1483263366);
|
|
|
|
|
ASSERT_TRUE(pd1->second.m_timestamp == 1483272963);
|
|
|
|
|
}
|
|
|
|
|
// tx keys
|
|
|
|
|
ASSERT_TRUE(w.m_tx_keys.size() == 2);
|
|
|
|
|
{
|
|
|
|
|
auto tx_key0 = w.m_tx_keys.begin();
|
|
|
|
|
auto tx_key1 = tx_key0;
|
|
|
|
|
++tx_key1;
|
|
|
|
|
if (epee::string_tools::pod_to_hex(tx_key0->first) == "6e7013684d35820f66c6679197ded9329bfe0e495effa47e7b25258799858dba")
|
|
|
|
|
swap(tx_key0, tx_key1);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tx_key0->first) == "b9aac8c020ab33859e0c0b6331f46a8780d349e7ac17b067116e2d87bf48daad");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tx_key1->first) == "6e7013684d35820f66c6679197ded9329bfe0e495effa47e7b25258799858dba");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tx_key0->second) == "bf3614c6de1d06c09add5d92a5265d8c76af706f7bc6ac830d6b0d109aa87701");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tx_key1->second) == "e556884246df5a787def6732c6ea38f1e092fa13e5ea98f732b99c07a6332003");
|
|
|
|
|
}
|
|
|
|
|
// confirmed txs
|
|
|
|
|
ASSERT_TRUE(w.m_confirmed_txs.size() == 1);
|
|
|
|
|
// tx notes
|
|
|
|
|
ASSERT_TRUE(w.m_tx_notes.size() == 2);
|
|
|
|
|
{
|
|
|
|
|
crypto::hash h[2];
|
|
|
|
|
epee::string_tools::hex_to_pod("15024343b38e77a1a9860dfed29921fa17e833fec837191a6b04fa7cb9605b8e", h[0]);
|
|
|
|
|
epee::string_tools::hex_to_pod("6e7013684d35820f66c6679197ded9329bfe0e495effa47e7b25258799858dba", h[1]);
|
|
|
|
|
ASSERT_TRUE(w.m_tx_notes.find(h[0])->second == "sample note");
|
|
|
|
|
ASSERT_TRUE(w.m_tx_notes.find(h[1])->second == "sample note 2");
|
|
|
|
|
}
|
|
|
|
|
// unconfirmed payments
|
|
|
|
|
ASSERT_TRUE(w.m_unconfirmed_payments.size() == 0);
|
|
|
|
|
// pub keys
|
|
|
|
|
ASSERT_TRUE(w.m_pub_keys.size() == 3);
|
|
|
|
|
{
|
|
|
|
|
crypto::public_key pubkey[3];
|
|
|
|
|
epee::string_tools::hex_to_pod("33f75f264574cb3a9ea5b24220a5312e183d36dc321c9091dfbb720922a4f7b0", pubkey[0]);
|
|
|
|
|
epee::string_tools::hex_to_pod("5066ff2ce9861b1d131cf16eeaa01264933a49f28242b97b153e922ec7b4b3cb", pubkey[1]);
|
|
|
|
|
epee::string_tools::hex_to_pod("0d8467e16e73d16510452b78823e082e05ee3a63788d40de577cf31eb555f0c8", pubkey[2]);
|
|
|
|
|
ASSERT_TRUE(w.m_pub_keys.find(pubkey[0])->second == 0);
|
|
|
|
|
ASSERT_TRUE(w.m_pub_keys.find(pubkey[1])->second == 1);
|
|
|
|
|
ASSERT_TRUE(w.m_pub_keys.find(pubkey[2])->second == 2);
|
|
|
|
|
}
|
|
|
|
|
// address book
|
|
|
|
|
ASSERT_TRUE(w.m_address_book.size() == 1);
|
|
|
|
|
{
|
|
|
|
|
auto address_book_row = w.m_address_book.begin();
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(address_book_row->m_address.m_spend_public_key) == "9bc53a6ff7b0831c9470f71b6b972dbe5ad1e8606f72682868b1dda64e119fb3");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(address_book_row->m_address.m_view_public_key) == "49fece1ef97dc0c0f7a5e2106e75e96edd910f7e86b56e1e308cd0cf734df191");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(address_book_row->m_payment_id) == "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef");
|
|
|
|
|
ASSERT_TRUE(address_book_row->m_description == "testnet wallet 9y52S6");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define OUTPUT_EXPORT_FILE_MAGIC "Monero output export\003"
|
|
|
|
|
TEST(Serialization, portability_outputs)
|
|
|
|
|
{
|
|
|
|
|
// read file
|
|
|
|
|
const std::string filename = "../data/outputs";
|
|
|
|
|
std::string data;
|
|
|
|
|
bool r = epee::file_io_utils::load_file_to_string(filename, data);
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
const size_t magiclen = strlen(OUTPUT_EXPORT_FILE_MAGIC);
|
|
|
|
|
ASSERT_FALSE(data.size() < magiclen || memcmp(data.data(), OUTPUT_EXPORT_FILE_MAGIC, magiclen));
|
|
|
|
|
// decrypt (copied from wallet2::decrypt)
|
|
|
|
|
auto decrypt = [] (const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated) -> string
|
|
|
|
|
{
|
|
|
|
|
const size_t prefix_size = sizeof(chacha8_iv) + (authenticated ? sizeof(crypto::signature) : 0);
|
|
|
|
|
if(ciphertext.size() < prefix_size)
|
|
|
|
|
return {};
|
|
|
|
|
crypto::chacha8_key key;
|
|
|
|
|
crypto::generate_chacha8_key(&skey, sizeof(skey), key);
|
|
|
|
|
const crypto::chacha8_iv &iv = *(const crypto::chacha8_iv*)&ciphertext[0];
|
|
|
|
|
std::string plaintext;
|
|
|
|
|
plaintext.resize(ciphertext.size() - prefix_size);
|
|
|
|
|
if (authenticated)
|
|
|
|
|
{
|
|
|
|
|
crypto::hash hash;
|
|
|
|
|
crypto::cn_fast_hash(ciphertext.data(), ciphertext.size() - sizeof(signature), hash);
|
|
|
|
|
crypto::public_key pkey;
|
|
|
|
|
crypto::secret_key_to_public_key(skey, pkey);
|
|
|
|
|
const crypto::signature &signature = *(const crypto::signature*)&ciphertext[ciphertext.size() - sizeof(crypto::signature)];
|
|
|
|
|
if(!crypto::check_signature(hash, pkey, signature))
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
crypto::chacha8(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, &plaintext[0]);
|
|
|
|
|
return std::move(plaintext);
|
|
|
|
|
};
|
|
|
|
|
crypto::secret_key view_secret_key;
|
|
|
|
|
epee::string_tools::hex_to_pod("339673bb1187e2f73ba7841ab6841c5553f96e9f13f8fe6612e69318db4e9d0a", view_secret_key);
|
|
|
|
|
bool authenticated = true;
|
|
|
|
|
data = decrypt(std::string(data, magiclen), view_secret_key, authenticated);
|
|
|
|
|
ASSERT_FALSE(data.empty());
|
|
|
|
|
// check public view/spend keys
|
|
|
|
|
const size_t headerlen = 2 * sizeof(crypto::public_key);
|
|
|
|
|
ASSERT_FALSE(data.size() < headerlen);
|
|
|
|
|
const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0];
|
|
|
|
|
const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[sizeof(crypto::public_key)];
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(public_spend_key) == "13daa2af00ad26a372d317195de0bdd716f7a05d33bc4d7aff1664b6ee93c060");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(public_view_key) == "e47d4b6df6ab7339539148c2a03ad3e2f3434e5ab2046848e1f21369a3937cad");
|
|
|
|
|
r = false;
|
|
|
|
|
std::vector<tools::wallet2::transfer_details> outputs;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
std::istringstream iss(std::string(data, headerlen));
|
|
|
|
|
boost::archive::portable_binary_iarchive ar(iss);
|
|
|
|
|
ar >> outputs;
|
|
|
|
|
r = true;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{}
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
/*
|
|
|
|
|
fields of tools::wallet2::transfer_details to be checked:
|
|
|
|
|
uint64_t m_block_height
|
|
|
|
|
cryptonote::transaction_prefix m_tx // TODO
|
|
|
|
|
crypto::hash m_txid
|
|
|
|
|
size_t m_internal_output_index
|
|
|
|
|
uint64_t m_global_output_index
|
|
|
|
|
bool m_spent
|
|
|
|
|
uint64_t m_spent_height
|
|
|
|
|
crypto::key_image m_key_image
|
|
|
|
|
rct::key m_mask
|
|
|
|
|
uint64_t m_amount
|
|
|
|
|
bool m_rct
|
|
|
|
|
bool m_key_image_known
|
|
|
|
|
size_t m_pk_index
|
|
|
|
|
*/
|
|
|
|
|
ASSERT_TRUE(outputs.size() == 3);
|
|
|
|
|
auto& td0 = outputs[0];
|
|
|
|
|
auto& td1 = outputs[1];
|
|
|
|
|
auto& td2 = outputs[2];
|
|
|
|
|
ASSERT_TRUE(td0.m_block_height == 818424);
|
|
|
|
|
ASSERT_TRUE(td1.m_block_height == 818522);
|
|
|
|
|
ASSERT_TRUE(td2.m_block_height == 818522);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_txid) == "15024343b38e77a1a9860dfed29921fa17e833fec837191a6b04fa7cb9605b8e");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_txid) == "ec34c9bb12b99af33d49691384eee5bed9171498ff04e59516505f35d1fc5efc");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_txid) == "6e7013684d35820f66c6679197ded9329bfe0e495effa47e7b25258799858dba");
|
|
|
|
|
ASSERT_TRUE(td0.m_internal_output_index == 0);
|
|
|
|
|
ASSERT_TRUE(td1.m_internal_output_index == 0);
|
|
|
|
|
ASSERT_TRUE(td2.m_internal_output_index == 1);
|
|
|
|
|
ASSERT_TRUE(td0.m_global_output_index == 19642);
|
|
|
|
|
ASSERT_TRUE(td1.m_global_output_index == 19757);
|
|
|
|
|
ASSERT_TRUE(td2.m_global_output_index == 19760);
|
|
|
|
|
ASSERT_TRUE (td0.m_spent);
|
|
|
|
|
ASSERT_FALSE(td1.m_spent);
|
|
|
|
|
ASSERT_FALSE(td2.m_spent);
|
|
|
|
|
ASSERT_TRUE(td0.m_spent_height == 0);
|
|
|
|
|
ASSERT_TRUE(td1.m_spent_height == 0);
|
|
|
|
|
ASSERT_TRUE(td2.m_spent_height == 0);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_key_image) == "c5680d3735b90871ca5e3d90cd82d6483eed1151b9ab75c2c8c3a7d89e00a5a8");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_key_image) == "d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_key_image) == "6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_mask) == "0100000000000000000000000000000000000000000000000000000000000000");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_mask) == "d3997a7b27fa199a377643b88cbd3f20f447496746dabe92d288730ecaeda007");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
|
|
|
|
|
ASSERT_TRUE(td0.m_amount == 13400845012231);
|
|
|
|
|
ASSERT_TRUE(td1.m_amount == 1200000000000);
|
|
|
|
|
ASSERT_TRUE(td2.m_amount == 11066009260865);
|
|
|
|
|
ASSERT_TRUE(td0.m_rct);
|
|
|
|
|
ASSERT_TRUE(td1.m_rct);
|
|
|
|
|
ASSERT_TRUE(td2.m_rct);
|
|
|
|
|
ASSERT_TRUE(td0.m_key_image_known);
|
|
|
|
|
ASSERT_TRUE(td1.m_key_image_known);
|
|
|
|
|
ASSERT_TRUE(td2.m_key_image_known);
|
|
|
|
|
ASSERT_TRUE(td0.m_pk_index == 0);
|
|
|
|
|
ASSERT_TRUE(td1.m_pk_index == 0);
|
|
|
|
|
ASSERT_TRUE(td2.m_pk_index == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\003"
|
|
|
|
|
TEST(Serialization, portability_unsigned_tx)
|
|
|
|
|
{
|
|
|
|
|
const string filename = "../data/unsigned_monero_tx";
|
|
|
|
|
std::string s;
|
|
|
|
|
const bool testnet = true;
|
|
|
|
|
bool r = epee::file_io_utils::load_file_to_string(filename, s);
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
const size_t magiclen = strlen(UNSIGNED_TX_PREFIX);
|
|
|
|
|
ASSERT_FALSE(strncmp(s.c_str(), UNSIGNED_TX_PREFIX, magiclen));
|
|
|
|
|
tools::wallet2::unsigned_tx_set exported_txs;
|
|
|
|
|
s = s.substr(magiclen);
|
|
|
|
|
r = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
std::istringstream iss(s);
|
|
|
|
|
boost::archive::portable_binary_iarchive ar(iss);
|
|
|
|
|
ar >> exported_txs;
|
|
|
|
|
r = true;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{}
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
/*
|
|
|
|
|
fields of tools::wallet2::unsigned_tx_set to be checked:
|
|
|
|
|
std::vector<tx_construction_data> txes
|
|
|
|
|
std::vector<wallet2::transfer_details> m_transfers
|
|
|
|
|
|
|
|
|
|
fields of toolw::wallet2::tx_construction_data to be checked:
|
|
|
|
|
std::vector<cryptonote::tx_source_entry> sources
|
|
|
|
|
cryptonote::tx_destination_entry change_dts
|
|
|
|
|
std::vector<cryptonote::tx_destination_entry> splitted_dsts
|
|
|
|
|
std::list<size_t> selected_transfers
|
|
|
|
|
std::vector<uint8_t> extra
|
|
|
|
|
uint64_t unlock_time
|
|
|
|
|
bool use_rct
|
|
|
|
|
std::vector<cryptonote::tx_destination_entry> dests
|
|
|
|
|
|
|
|
|
|
fields of cryptonote::tx_source_entry to be checked:
|
|
|
|
|
std::vector<std::pair<uint64_t, rct::ctkey>> outputs
|
|
|
|
|
size_t real_output
|
|
|
|
|
crypto::public_key real_out_tx_key
|
|
|
|
|
size_t real_output_in_tx_index
|
|
|
|
|
uint64_t amount
|
|
|
|
|
bool rct
|
|
|
|
|
rct::key mask
|
|
|
|
|
|
|
|
|
|
fields of cryptonote::tx_destination_entry to be checked:
|
|
|
|
|
uint64_t amount
|
|
|
|
|
account_public_address addr
|
|
|
|
|
*/
|
|
|
|
|
// txes
|
|
|
|
|
ASSERT_TRUE(exported_txs.txes.size() == 1);
|
|
|
|
|
auto& tcd = exported_txs.txes[0];
|
|
|
|
|
// tcd.sources
|
|
|
|
|
ASSERT_TRUE(tcd.sources.size() == 1);
|
|
|
|
|
auto& tse = tcd.sources[0];
|
|
|
|
|
// tcd.sources[0].outputs
|
|
|
|
|
ASSERT_TRUE(tse.outputs.size() == 5);
|
|
|
|
|
auto& out0 = tse.outputs[0];
|
|
|
|
|
auto& out1 = tse.outputs[1];
|
|
|
|
|
auto& out2 = tse.outputs[2];
|
|
|
|
|
auto& out3 = tse.outputs[3];
|
|
|
|
|
auto& out4 = tse.outputs[4];
|
|
|
|
|
ASSERT_TRUE(out0.first == 6295);
|
|
|
|
|
ASSERT_TRUE(out1.first == 14302);
|
|
|
|
|
ASSERT_TRUE(out2.first == 17598);
|
|
|
|
|
ASSERT_TRUE(out3.first == 18671);
|
|
|
|
|
ASSERT_TRUE(out4.first == 19760);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out0.second) == "e7272cb589954ddeedd20de9411ed57265f154d41f33cec9ff69e5d642e09814096490b0ac85308342acf436cc0270d53abef9dc04c6202f2459e879bfd40ce6");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out1.second) == "c3a9f49d1fe75939cc3feb39871ce0a7366c2879a63faa1a5cf34e65723b120a272ff0c7d84ab8b6ee3528d196450b0e28b3fed276bc2597a2b5b17afb9354ab");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out2.second) == "176e239c8c39000c2275e2f63ed7d55c55e0843524091522bbd3d3b869044969021fad70fc1244115449d4754829ae7c47346342ee5d52a2cdd47dfc351d0ab0");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out3.second) == "ef12d7946302fb064f2ba9df1a73d72233ac74664ed3b370580fa3bdc377542ad93f64898bd95851d6efe0d7bf2dbbea9b7c6b3c57e2c807e7b17d55b4622259");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out4.second) == "0d8467e16e73d16510452b78823e082e05ee3a63788d40de577cf31eb555f0c8525096cbc88d00a841eed66f3cdb6f0a018e6ce9fb9433ed61afba15cbbebd04");
|
|
|
|
|
// tcd.sources[0].{real_output, real_out_tx_key, real_output_in_tx_index, amount, rct, mask}
|
|
|
|
|
ASSERT_TRUE(tse.real_output == 4);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.real_out_tx_key) == "4d86c7ba1c285fe4bc1cd7b54ba894fa89fa02fc6b0bbeea67d53251acd14a05");
|
|
|
|
|
ASSERT_TRUE(tse.real_output_in_tx_index == 1);
|
|
|
|
|
ASSERT_TRUE(tse.amount == 11066009260865);
|
|
|
|
|
ASSERT_TRUE(tse.rct);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
|
|
|
|
|
// tcd.change_dts
|
|
|
|
|
ASSERT_TRUE(tcd.change_dts.amount == 9631208773403);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, tcd.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk");
|
|
|
|
|
// tcd.splitted_dsts
|
|
|
|
|
ASSERT_TRUE(tcd.splitted_dsts.size() == 2);
|
|
|
|
|
auto& splitted_dst0 = tcd.splitted_dsts[0];
|
|
|
|
|
auto& splitted_dst1 = tcd.splitted_dsts[1];
|
|
|
|
|
ASSERT_TRUE(splitted_dst0.amount == 1400000000000);
|
|
|
|
|
ASSERT_TRUE(splitted_dst1.amount == 9631208773403);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, splitted_dst0.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA");
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, splitted_dst1.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk");
|
|
|
|
|
// tcd.selected_transfers
|
|
|
|
|
ASSERT_TRUE(tcd.selected_transfers.size() == 1);
|
|
|
|
|
ASSERT_TRUE(tcd.selected_transfers.front() == 2);
|
|
|
|
|
// tcd.extra
|
|
|
|
|
ASSERT_TRUE(tcd.extra.size() == 68);
|
|
|
|
|
string tcd_extra_str = epee::string_tools::buff_to_hex(string(reinterpret_cast<char*>(tcd.extra.data()), tcd.extra.size()));
|
|
|
|
|
ASSERT_TRUE(tcd_extra_str == "0x2 0x21 0x0 0xf8 0xd 0xbc 0xfc 0xa2 0x2d 0x84 0x1e 0xa0 0x46 0x18 0x7a 0x5b 0x19 0xea 0x4d 0xd1 0xa2 0x8a 0x58 0xa8 0x72 0x9 0xd5 0xdf 0x2 0x30 0x60 0xac 0x9e 0x48 0x84 0x1 0xb2 0xfd 0x5d 0x4e 0x45 0x8b 0xf1 0x28 0xa0 0xc8 0x30 0xd1 0x35 0x4f 0x47 0xb9 0xed 0xc9 0x82 0x8c 0x83 0x37 0x7d 0xb6 0xb5 0xe5 0x3d 0xff 0x64 0xb0 0xde 0x7f ");
|
|
|
|
|
// tcd.{unlock_time, use_rct}
|
|
|
|
|
ASSERT_TRUE(tcd.unlock_time == 0);
|
|
|
|
|
ASSERT_TRUE(tcd.use_rct);
|
|
|
|
|
// tcd.dests
|
|
|
|
|
ASSERT_TRUE(tcd.dests.size() == 1);
|
|
|
|
|
auto& dest = tcd.dests[0];
|
|
|
|
|
ASSERT_TRUE(dest.amount == 1400000000000);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, dest.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA");
|
|
|
|
|
// transfers
|
|
|
|
|
ASSERT_TRUE(exported_txs.transfers.size() == 3);
|
|
|
|
|
auto& td0 = exported_txs.transfers[0];
|
|
|
|
|
auto& td1 = exported_txs.transfers[1];
|
|
|
|
|
auto& td2 = exported_txs.transfers[2];
|
|
|
|
|
ASSERT_TRUE(td0.m_block_height == 818424);
|
|
|
|
|
ASSERT_TRUE(td1.m_block_height == 818522);
|
|
|
|
|
ASSERT_TRUE(td2.m_block_height == 818522);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_txid) == "15024343b38e77a1a9860dfed29921fa17e833fec837191a6b04fa7cb9605b8e");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_txid) == "ec34c9bb12b99af33d49691384eee5bed9171498ff04e59516505f35d1fc5efc");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_txid) == "6e7013684d35820f66c6679197ded9329bfe0e495effa47e7b25258799858dba");
|
|
|
|
|
ASSERT_TRUE(td0.m_internal_output_index == 0);
|
|
|
|
|
ASSERT_TRUE(td1.m_internal_output_index == 0);
|
|
|
|
|
ASSERT_TRUE(td2.m_internal_output_index == 1);
|
|
|
|
|
ASSERT_TRUE(td0.m_global_output_index == 19642);
|
|
|
|
|
ASSERT_TRUE(td1.m_global_output_index == 19757);
|
|
|
|
|
ASSERT_TRUE(td2.m_global_output_index == 19760);
|
|
|
|
|
ASSERT_TRUE (td0.m_spent);
|
|
|
|
|
ASSERT_FALSE(td1.m_spent);
|
|
|
|
|
ASSERT_FALSE(td2.m_spent);
|
|
|
|
|
ASSERT_TRUE(td0.m_spent_height == 0);
|
|
|
|
|
ASSERT_TRUE(td1.m_spent_height == 0);
|
|
|
|
|
ASSERT_TRUE(td2.m_spent_height == 0);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_key_image) == "c5680d3735b90871ca5e3d90cd82d6483eed1151b9ab75c2c8c3a7d89e00a5a8");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_key_image) == "d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_key_image) == "6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td0.m_mask) == "0100000000000000000000000000000000000000000000000000000000000000");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td1.m_mask) == "d3997a7b27fa199a377643b88cbd3f20f447496746dabe92d288730ecaeda007");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(td2.m_mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
|
|
|
|
|
ASSERT_TRUE(td0.m_amount == 13400845012231);
|
|
|
|
|
ASSERT_TRUE(td1.m_amount == 1200000000000);
|
|
|
|
|
ASSERT_TRUE(td2.m_amount == 11066009260865);
|
|
|
|
|
ASSERT_TRUE(td0.m_rct);
|
|
|
|
|
ASSERT_TRUE(td1.m_rct);
|
|
|
|
|
ASSERT_TRUE(td2.m_rct);
|
|
|
|
|
ASSERT_TRUE(td0.m_key_image_known);
|
|
|
|
|
ASSERT_TRUE(td1.m_key_image_known);
|
|
|
|
|
ASSERT_TRUE(td2.m_key_image_known);
|
|
|
|
|
ASSERT_TRUE(td0.m_pk_index == 0);
|
|
|
|
|
ASSERT_TRUE(td1.m_pk_index == 0);
|
|
|
|
|
ASSERT_TRUE(td2.m_pk_index == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SIGNED_TX_PREFIX "Monero signed tx set\003"
|
|
|
|
|
TEST(Serialization, portability_signed_tx)
|
|
|
|
|
{
|
|
|
|
|
const string filename = "../data/signed_monero_tx";
|
|
|
|
|
const bool testnet = true;
|
|
|
|
|
std::string s;
|
|
|
|
|
bool r = epee::file_io_utils::load_file_to_string(filename, s);
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
const size_t magiclen = strlen(SIGNED_TX_PREFIX);
|
|
|
|
|
ASSERT_FALSE(strncmp(s.c_str(), SIGNED_TX_PREFIX, magiclen));
|
|
|
|
|
tools::wallet2::signed_tx_set exported_txs;
|
|
|
|
|
s = s.substr(magiclen);
|
|
|
|
|
r = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
std::istringstream iss(s);
|
|
|
|
|
boost::archive::portable_binary_iarchive ar(iss);
|
|
|
|
|
ar >> exported_txs;
|
|
|
|
|
r = true;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{}
|
|
|
|
|
ASSERT_TRUE(r);
|
|
|
|
|
/*
|
|
|
|
|
fields of tools::wallet2::signed_tx_set to be checked:
|
|
|
|
|
std::vector<pending_tx> ptx
|
|
|
|
|
std::vector<crypto::key_image> key_images
|
|
|
|
|
|
|
|
|
|
fields of tools::walllet2::pending_tx to be checked:
|
|
|
|
|
cryptonote::transaction tx // TODO
|
|
|
|
|
uint64_t dust
|
|
|
|
|
uint64_t fee
|
|
|
|
|
bool dust_added_to_fee
|
|
|
|
|
cryptonote::tx_destination_entry change_dts
|
|
|
|
|
std::list<size_t> selected_transfers
|
|
|
|
|
std::string key_images
|
|
|
|
|
crypto::secret_key tx_key
|
|
|
|
|
std::vector<cryptonote::tx_destination_entry> dests
|
|
|
|
|
tx_construction_data construction_data
|
|
|
|
|
*/
|
|
|
|
|
// ptx
|
|
|
|
|
ASSERT_TRUE(exported_txs.ptx.size() == 1);
|
|
|
|
|
auto& ptx = exported_txs.ptx[0];
|
|
|
|
|
// ptx.{dust, fee, dust_added_to_fee}
|
|
|
|
|
ASSERT_TRUE (ptx.dust == 0);
|
|
|
|
|
ASSERT_TRUE (ptx.fee == 34800487462);
|
|
|
|
|
ASSERT_FALSE(ptx.dust_added_to_fee);
|
|
|
|
|
// ptx.change.{amount, addr}
|
|
|
|
|
ASSERT_TRUE(ptx.change_dts.amount == 9631208773403);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, ptx.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk");
|
|
|
|
|
// ptx.selected_transfers
|
|
|
|
|
ASSERT_TRUE(ptx.selected_transfers.size() == 1);
|
|
|
|
|
ASSERT_TRUE(ptx.selected_transfers.front() == 2);
|
|
|
|
|
// ptx.{key_images, tx_key}
|
|
|
|
|
ASSERT_TRUE(ptx.key_images == "<6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76> ");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(ptx.tx_key) == "0100000000000000000000000000000000000000000000000000000000000000");
|
|
|
|
|
// ptx.dests
|
|
|
|
|
ASSERT_TRUE(ptx.dests.size() == 1);
|
|
|
|
|
ASSERT_TRUE(ptx.dests[0].amount == 1400000000000);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, ptx.dests[0].addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA");
|
|
|
|
|
// ptx.construction_data
|
|
|
|
|
auto& tcd = ptx.construction_data;
|
|
|
|
|
ASSERT_TRUE(tcd.sources.size() == 1);
|
|
|
|
|
auto& tse = tcd.sources[0];
|
|
|
|
|
// ptx.construction_data.sources[0].outputs
|
|
|
|
|
ASSERT_TRUE(tse.outputs.size() == 5);
|
|
|
|
|
auto& out0 = tse.outputs[0];
|
|
|
|
|
auto& out1 = tse.outputs[1];
|
|
|
|
|
auto& out2 = tse.outputs[2];
|
|
|
|
|
auto& out3 = tse.outputs[3];
|
|
|
|
|
auto& out4 = tse.outputs[4];
|
|
|
|
|
ASSERT_TRUE(out0.first == 6295);
|
|
|
|
|
ASSERT_TRUE(out1.first == 14302);
|
|
|
|
|
ASSERT_TRUE(out2.first == 17598);
|
|
|
|
|
ASSERT_TRUE(out3.first == 18671);
|
|
|
|
|
ASSERT_TRUE(out4.first == 19760);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out0.second) == "e7272cb589954ddeedd20de9411ed57265f154d41f33cec9ff69e5d642e09814096490b0ac85308342acf436cc0270d53abef9dc04c6202f2459e879bfd40ce6");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out1.second) == "c3a9f49d1fe75939cc3feb39871ce0a7366c2879a63faa1a5cf34e65723b120a272ff0c7d84ab8b6ee3528d196450b0e28b3fed276bc2597a2b5b17afb9354ab");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out2.second) == "176e239c8c39000c2275e2f63ed7d55c55e0843524091522bbd3d3b869044969021fad70fc1244115449d4754829ae7c47346342ee5d52a2cdd47dfc351d0ab0");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out3.second) == "ef12d7946302fb064f2ba9df1a73d72233ac74664ed3b370580fa3bdc377542ad93f64898bd95851d6efe0d7bf2dbbea9b7c6b3c57e2c807e7b17d55b4622259");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(out4.second) == "0d8467e16e73d16510452b78823e082e05ee3a63788d40de577cf31eb555f0c8525096cbc88d00a841eed66f3cdb6f0a018e6ce9fb9433ed61afba15cbbebd04");
|
|
|
|
|
// ptx.construction_data.sources[0].{real_output, real_out_tx_key, real_output_in_tx_index, amount, rct, mask}
|
|
|
|
|
ASSERT_TRUE(tse.real_output == 4);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.real_out_tx_key) == "4d86c7ba1c285fe4bc1cd7b54ba894fa89fa02fc6b0bbeea67d53251acd14a05");
|
|
|
|
|
ASSERT_TRUE(tse.real_output_in_tx_index == 1);
|
|
|
|
|
ASSERT_TRUE(tse.amount == 11066009260865);
|
|
|
|
|
ASSERT_TRUE(tse.rct);
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703");
|
|
|
|
|
// ptx.construction_data.change_dts
|
|
|
|
|
ASSERT_TRUE(tcd.change_dts.amount == 9631208773403);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, tcd.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk");
|
|
|
|
|
// ptx.construction_data.splitted_dsts
|
|
|
|
|
ASSERT_TRUE(tcd.splitted_dsts.size() == 2);
|
|
|
|
|
auto& splitted_dst0 = tcd.splitted_dsts[0];
|
|
|
|
|
auto& splitted_dst1 = tcd.splitted_dsts[1];
|
|
|
|
|
ASSERT_TRUE(splitted_dst0.amount == 1400000000000);
|
|
|
|
|
ASSERT_TRUE(splitted_dst1.amount == 9631208773403);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, splitted_dst0.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA");
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, splitted_dst1.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk");
|
|
|
|
|
// ptx.construction_data.selected_transfers
|
|
|
|
|
ASSERT_TRUE(tcd.selected_transfers.size() == 1);
|
|
|
|
|
ASSERT_TRUE(tcd.selected_transfers.front() == 2);
|
|
|
|
|
// ptx.construction_data.extra
|
|
|
|
|
ASSERT_TRUE(tcd.extra.size() == 68);
|
|
|
|
|
string tcd_extra_str = epee::string_tools::buff_to_hex(string(reinterpret_cast<char*>(tcd.extra.data()), tcd.extra.size()));
|
|
|
|
|
ASSERT_TRUE(tcd_extra_str == "0x2 0x21 0x0 0xf8 0xd 0xbc 0xfc 0xa2 0x2d 0x84 0x1e 0xa0 0x46 0x18 0x7a 0x5b 0x19 0xea 0x4d 0xd1 0xa2 0x8a 0x58 0xa8 0x72 0x9 0xd5 0xdf 0x2 0x30 0x60 0xac 0x9e 0x48 0x84 0x1 0xb2 0xfd 0x5d 0x4e 0x45 0x8b 0xf1 0x28 0xa0 0xc8 0x30 0xd1 0x35 0x4f 0x47 0xb9 0xed 0xc9 0x82 0x8c 0x83 0x37 0x7d 0xb6 0xb5 0xe5 0x3d 0xff 0x64 0xb0 0xde 0x7f ");
|
|
|
|
|
// ptx.construction_data.{unlock_time, use_rct}
|
|
|
|
|
ASSERT_TRUE(tcd.unlock_time == 0);
|
|
|
|
|
ASSERT_TRUE(tcd.use_rct);
|
|
|
|
|
// ptx.construction_data.dests
|
|
|
|
|
ASSERT_TRUE(tcd.dests.size() == 1);
|
|
|
|
|
auto& dest = tcd.dests[0];
|
|
|
|
|
ASSERT_TRUE(dest.amount == 1400000000000);
|
|
|
|
|
ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, dest.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA");
|
|
|
|
|
// key_images
|
|
|
|
|
ASSERT_TRUE(exported_txs.key_images.size() == 3);
|
|
|
|
|
auto& ki0 = exported_txs.key_images[0];
|
|
|
|
|
auto& ki1 = exported_txs.key_images[1];
|
|
|
|
|
auto& ki2 = exported_txs.key_images[2];
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(ki0) == "c5680d3735b90871ca5e3d90cd82d6483eed1151b9ab75c2c8c3a7d89e00a5a8");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(ki1) == "d54cbd435a8d636ad9b01b8d4f3eb13bd0cf1ce98eddf53ab1617f9b763e66c0");
|
|
|
|
|
ASSERT_TRUE(epee::string_tools::pod_to_hex(ki2) == "6c3cd6af97c4070a7aef9b1344e7463e29c7cd245076fdb65da447a34da3ca76");
|
|
|
|
|
}
|
|
|
|
|