Electroneum
Loading...
Searching...
No Matches
json_serialization.cpp
Go to the documentation of this file.
1
2#include <boost/optional/optional.hpp>
3#include <boost/range/adaptor/indexed.hpp>
4#include <gtest/gtest.h>
6#include <vector>
7
8#include "crypto/hash.h"
14
15
16namespace
17{
19 make_miner_transaction(cryptonote::account_public_address const& to)
20 {
22 if (!cryptonote::construct_miner_tx(0, 0, 5000, 500, 500, to, tx))
23 throw std::runtime_error{"transaction construction error"};
24
25 crypto::hash id{0};
27 throw std::runtime_error{"could not get transaction hash"};
28
29 return tx;
30 }
31
33 make_transaction(
34 cryptonote::account_keys const& from,
35 std::vector<cryptonote::transaction> const& sources,
36 std::vector<cryptonote::account_public_address> const& destinations,
37 bool rct,
38 bool bulletproof)
39 {
40 std::uint64_t source_amount = 0;
41 std::vector<cryptonote::tx_source_entry> actual_sources;
42 for (auto const& source : sources)
43 {
44 std::vector<cryptonote::tx_extra_field> extra_fields;
45 if (!cryptonote::parse_tx_extra(source.extra, extra_fields))
46 throw std::runtime_error{"invalid transaction"};
47
49 if (!cryptonote::find_tx_extra_field_by_type(extra_fields, key_field))
50 throw std::runtime_error{"invalid transaction"};
51
52 for (auto const& input : boost::adaptors::index(source.vout))
53 {
54 source_amount += input.value().amount;
55 auto const& key = boost::get<cryptonote::txout_to_key>(input.value().target);
56
57 actual_sources.push_back(
58 {{}, 0, key_field.pub_key, {}, std::size_t(input.index()), input.value().amount, rct, rct::identity()}
59 );
60
61 for (unsigned ring = 0; ring < 10; ++ring)
62 actual_sources.back().push_output(input.index(), key.key, input.value().amount);
63 }
64 }
65
66 std::vector<cryptonote::tx_destination_entry> to;
67 for (auto const& destination : destinations)
68 to.push_back({(source_amount / destinations.size()), destination, false});
69
71
72 crypto::secret_key tx_key{};
73 std::vector<crypto::secret_key> extra_keys{};
74
75 std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
76 subaddresses[from.m_account_address.m_spend_public_key] = {0,0};
77
78 if (!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, {}, tx, 0, tx_key, extra_keys, rct, { bulletproof ? rct::RangeProofBulletproof : rct::RangeProofBorromean, bulletproof ? 2 : 0 }))
79 throw std::runtime_error{"transaction construction error"};
80
81 return tx;
82 }
83} // anonymous
84
85TEST(JsonSerialization, MinerTransaction)
86{
88 acct.generate();
89 const auto miner_tx = make_miner_transaction(acct.get_keys().m_account_address);
90
91 crypto::hash tx_hash{};
93
94 rapidjson::Document doc;
95 cryptonote::json::toJsonValue(doc, miner_tx, doc);
96
97 cryptonote::transaction miner_tx_copy;
98 cryptonote::json::fromJsonValue(doc, miner_tx_copy);
99
100 crypto::hash tx_copy_hash{};
101 ASSERT_TRUE(cryptonote::get_transaction_hash(miner_tx_copy, tx_copy_hash));
102 EXPECT_EQ(tx_hash, tx_copy_hash);
103
104 cryptonote::blobdata tx_bytes{};
105 cryptonote::blobdata tx_copy_bytes{};
106
108 ASSERT_TRUE(cryptonote::t_serializable_object_to_blob(miner_tx_copy, tx_copy_bytes));
109
110 EXPECT_EQ(tx_bytes, tx_copy_bytes);
111}
112
113TEST(JsonSerialization, RegularTransaction)
114{
116 acct1.generate();
117
119 acct2.generate();
120
121 const auto miner_tx = make_miner_transaction(acct1.get_keys().m_account_address);
122 const auto tx = make_transaction(
123 acct1.get_keys(), {miner_tx}, {acct2.get_keys().m_account_address}, false, false
124 );
125
126 crypto::hash tx_hash{};
128
129 rapidjson::Document doc;
130 cryptonote::json::toJsonValue(doc, tx, doc);
131
133 cryptonote::json::fromJsonValue(doc, tx_copy);
134
135 crypto::hash tx_copy_hash{};
136 ASSERT_TRUE(cryptonote::get_transaction_hash(tx_copy, tx_copy_hash));
137 EXPECT_EQ(tx_hash, tx_copy_hash);
138
139 cryptonote::blobdata tx_bytes{};
140 cryptonote::blobdata tx_copy_bytes{};
141
144
145 EXPECT_EQ(tx_bytes, tx_copy_bytes);
146}
147
148TEST(JsonSerialization, RingctTransaction)
149{
151 acct1.generate();
152
154 acct2.generate();
155
156 const auto miner_tx = make_miner_transaction(acct1.get_keys().m_account_address);
157 const auto tx = make_transaction(
158 acct1.get_keys(), {miner_tx}, {acct2.get_keys().m_account_address}, true, false
159 );
160
161 crypto::hash tx_hash{};
163
164 rapidjson::Document doc;
165 cryptonote::json::toJsonValue(doc, tx, doc);
166
168 cryptonote::json::fromJsonValue(doc, tx_copy);
169
170 crypto::hash tx_copy_hash{};
171 ASSERT_TRUE(cryptonote::get_transaction_hash(tx_copy, tx_copy_hash));
172 EXPECT_EQ(tx_hash, tx_copy_hash);
173
174 cryptonote::blobdata tx_bytes{};
175 cryptonote::blobdata tx_copy_bytes{};
176
179
180 EXPECT_EQ(tx_bytes, tx_copy_bytes);
181}
182
183TEST(JsonSerialization, BulletproofTransaction)
184{
186 acct1.generate();
187
189 acct2.generate();
190
191 const auto miner_tx = make_miner_transaction(acct1.get_keys().m_account_address);
192 const auto tx = make_transaction(
193 acct1.get_keys(), {miner_tx}, {acct2.get_keys().m_account_address}, true, true
194 );
195
196 crypto::hash tx_hash{};
198
199 rapidjson::Document doc;
200 cryptonote::json::toJsonValue(doc, tx, doc);
201
203 cryptonote::json::fromJsonValue(doc, tx_copy);
204
205 crypto::hash tx_copy_hash{};
206 ASSERT_TRUE(cryptonote::get_transaction_hash(tx_copy, tx_copy_hash));
207 EXPECT_EQ(tx_hash, tx_copy_hash);
208
209 cryptonote::blobdata tx_bytes{};
210 cryptonote::blobdata tx_copy_bytes{};
211
214
215 EXPECT_EQ(tx_bytes, tx_copy_bytes);
216}
217
crypto::secret_key generate(const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false, bool two_random=false)
Definition account.cpp:158
const account_keys & get_keys() const
Definition account.cpp:264
#define EXPECT_EQ(val1, val2)
Definition gtest.h:1922
#define TEST(test_case_name, test_name)
Definition gtest.h:2187
#define ASSERT_TRUE(condition)
Definition gtest.h:1865
const char * key
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS hash
Definition hash.h:50
bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, const uint32_t account_major_offset, const cryptonote::network_type nettype)
crypto::hash get_transaction_hash(const transaction &t)
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction &tx, const blobdata &extra_nonce, size_t max_outs, uint8_t hard_fork_version, network_type nettype)
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
std::string blobdata
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
@ RangeProofBorromean
Definition rctTypes.h:235
@ RangeProofBulletproof
Definition rctTypes.h:235
key identity()
Definition rctOps.h:73
const CharType(& source)[N]
Definition pointer.h:1147
account_public_address m_account_address
Definition account.h:43
crypto::public_key pub_key
Definition tx_extra.h:102