Electroneum
Loading...
Searching...
No Matches
chain_switch_1.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32#include "chaingen.h"
33#include "chain_switch_1.h"
34
35using namespace epee;
36using namespace cryptonote;
37
38
44
45
46//-----------------------------------------------------------------------------------------------------
47bool gen_chain_switch_1::generate(std::vector<test_event_entry>& events) const
48{
49 uint64_t ts_start = 1338224400;
50 /*
51 (0 )-(1 )-(2 ) -(3 )-(4 ) <- main chain, until 7 isn't connected
52 \ |-(5 )-(6 )-(7 )| <- alt chain, until 7 isn't connected
53
54 transactions ([n] - tx amount, (m) - block):
55 (1) : miner -[ 5]-> account_1 ( +5 in main chain, +5 in alt chain)
56 (3) : miner -[ 7]-> account_2 ( +7 in main chain, +0 in alt chain), tx will be in tx pool after switch
57 (4), (6): miner -[11]-> account_3 (+11 in main chain, +11 in alt chain)
58 (5) : miner -[13]-> account_4 ( +0 in main chain, +13 in alt chain), tx will be in tx pool before switch
59
60 transactions orders ([n] - tx amount, (m) - block):
61 miner -[1], [2]-> account_1: in main chain (3), (3), in alt chain (5), (6)
62 miner -[1], [2]-> account_2: in main chain (3), (4), in alt chain (5), (5)
63 miner -[1], [2]-> account_3: in main chain (3), (4), in alt chain (6), (5)
64 miner -[1], [2]-> account_4: in main chain (4), (3), in alt chain (5), (6)
65 */
66
67 GENERATE_ACCOUNT(miner_account);
68
69 // events
70 MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start); // 0
71 MAKE_ACCOUNT(events, recipient_account_1); // 1
72 MAKE_ACCOUNT(events, recipient_account_2); // 2
73 MAKE_ACCOUNT(events, recipient_account_3); // 3
74 MAKE_ACCOUNT(events, recipient_account_4); // 4
75 REWIND_BLOCKS(events, blk_0r, blk_0, miner_account) // <N blocks>
76 MAKE_TX(events, tx_00, miner_account, recipient_account_1, MK_COINS(5), blk_0); // 5 + N
77 MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_account, tx_00); // 6 + N
78 MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_account); // 7 + N
79 REWIND_BLOCKS(events, blk_2r, blk_2, miner_account) // <N blocks>
80
81 // Transactions to test account balances after switch
82 MAKE_TX_LIST_START(events, txs_blk_3, miner_account, recipient_account_2, MK_COINS(7), blk_2); // 8 + 2N
83 MAKE_TX_LIST_START(events, txs_blk_4, miner_account, recipient_account_3, MK_COINS(11), blk_2); // 9 + 2N
84 MAKE_TX_LIST_START(events, txs_blk_5, miner_account, recipient_account_4, MK_COINS(13), blk_2); // 10 + 2N
85 std::list<transaction> txs_blk_6;
86 txs_blk_6.push_back(txs_blk_4.front());
87
88 // Transactions, that has different order in alt block chains
89 MAKE_TX_LIST(events, txs_blk_3, miner_account, recipient_account_1, MK_COINS(1), blk_2); // 11 + 2N
90 txs_blk_5.push_back(txs_blk_3.back());
91 MAKE_TX_LIST(events, txs_blk_3, miner_account, recipient_account_1, MK_COINS(2), blk_2); // 12 + 2N
92 txs_blk_6.push_back(txs_blk_3.back());
93
94 MAKE_TX_LIST(events, txs_blk_3, miner_account, recipient_account_2, MK_COINS(1), blk_2); // 13 + 2N
95 txs_blk_5.push_back(txs_blk_3.back());
96 MAKE_TX_LIST(events, txs_blk_4, miner_account, recipient_account_2, MK_COINS(2), blk_2); // 14 + 2N
97 txs_blk_5.push_back(txs_blk_4.back());
98
99 MAKE_TX_LIST(events, txs_blk_3, miner_account, recipient_account_3, MK_COINS(1), blk_2); // 15 + 2N
100 txs_blk_6.push_back(txs_blk_3.back());
101 MAKE_TX_LIST(events, txs_blk_4, miner_account, recipient_account_3, MK_COINS(2), blk_2); // 16 + 2N
102 txs_blk_5.push_back(txs_blk_4.back());
103
104 MAKE_TX_LIST(events, txs_blk_4, miner_account, recipient_account_4, MK_COINS(1), blk_2); // 17 + 2N
105 txs_blk_5.push_back(txs_blk_4.back());
106 MAKE_TX_LIST(events, txs_blk_3, miner_account, recipient_account_4, MK_COINS(2), blk_2); // 18 + 2N
107 txs_blk_6.push_back(txs_blk_3.back());
108
109 MAKE_NEXT_BLOCK_TX_LIST(events, blk_3, blk_2r, miner_account, txs_blk_3); // 19 + 2N
110 MAKE_NEXT_BLOCK_TX_LIST(events, blk_4, blk_3, miner_account, txs_blk_4); // 20 + 2N
111 //split
112 MAKE_NEXT_BLOCK_TX_LIST(events, blk_5, blk_2r, miner_account, txs_blk_5); // 22 + 2N
113 MAKE_NEXT_BLOCK_TX_LIST(events, blk_6, blk_5, miner_account, txs_blk_6); // 23 + 2N
114 DO_CALLBACK(events, "check_split_not_switched"); // 21 + 2N
115 MAKE_NEXT_BLOCK(events, blk_7, blk_6, miner_account); // 24 + 2N
116 DO_CALLBACK(events, "check_split_switched"); // 25 + 2N
117
118 return true;
119}
120
121
122//-----------------------------------------------------------------------------------------------------
123bool gen_chain_switch_1::check_split_not_switched(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
124{
125 DEFINE_TESTS_ERROR_CONTEXT("gen_chain_switch_1::check_split_not_switched");
126
127 m_recipient_account_1 = boost::get<account_base>(events[1]);
128 m_recipient_account_2 = boost::get<account_base>(events[2]);
129 m_recipient_account_3 = boost::get<account_base>(events[3]);
130 m_recipient_account_4 = boost::get<account_base>(events[4]);
131
132 std::vector<block> blocks;
133 bool r = c.get_blocks(0, 10000, blocks);
136 CHECK_TEST_CONDITION(blocks.back() == boost::get<block>(events[20 + 2 * CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW])); // blk_4
137
139
140 std::vector<cryptonote::block> chain;
141 map_hash2tx_t mtx;
142 r = find_block_chain(events, chain, mtx, get_block_hash(blocks.back()));
144 CHECK_EQ(MK_COINS(8), get_balance(m_recipient_account_1, chain, mtx));
145 CHECK_EQ(MK_COINS(10), get_balance(m_recipient_account_2, chain, mtx));
146 CHECK_EQ(MK_COINS(14), get_balance(m_recipient_account_3, chain, mtx));
147 CHECK_EQ(MK_COINS(3), get_balance(m_recipient_account_4, chain, mtx));
148
149 std::vector<transaction> tx_pool;
150 r = c.get_pool_transactions(tx_pool);
152 CHECK_EQ(1, tx_pool.size());
153
154 std::vector<size_t> tx_outs;
155 uint64_t transfered;
156 lookup_acc_outs(m_recipient_account_4.get_keys(), tx_pool.front(), get_tx_pub_key_from_extra(tx_pool.front()), get_additional_tx_pub_keys_from_extra(tx_pool.front()), tx_outs, transfered);
157 CHECK_EQ(MK_COINS(13), transfered);
158
159 m_chain_1.swap(blocks);
160 m_tx_pool.swap(tx_pool);
161
162 return true;
163}
164
165//-----------------------------------------------------------------------------------------------------
166bool gen_chain_switch_1::check_split_switched(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
167{
168 DEFINE_TESTS_ERROR_CONTEXT("gen_chain_switch_1::check_split_switched");
169
170 std::vector<block> blocks;
171 bool r = c.get_blocks(0, 10000, blocks);
174 auto it = blocks.end();
175 --it; --it; --it;
176 CHECK_TEST_CONDITION(std::equal(blocks.begin(), it, m_chain_1.begin()));
177 CHECK_TEST_CONDITION(blocks.back() == boost::get<block>(events[24 + 2 * CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW])); // blk_7
178
179 std::vector<block> alt_blocks;
180 r = c.get_alternative_blocks(alt_blocks);
183
184 // Some blocks that were in main chain are in alt chain now
185 BOOST_FOREACH(block b, alt_blocks)
186 {
187 CHECK_TEST_CONDITION(m_chain_1.end() != std::find(m_chain_1.begin(), m_chain_1.end(), b));
188 }
189
190 std::vector<cryptonote::block> chain;
191 map_hash2tx_t mtx;
192 r = find_block_chain(events, chain, mtx, get_block_hash(blocks.back()));
194 CHECK_EQ(MK_COINS(8), get_balance(m_recipient_account_1, chain, mtx));
195 CHECK_EQ(MK_COINS(3), get_balance(m_recipient_account_2, chain, mtx));
196 CHECK_EQ(MK_COINS(14), get_balance(m_recipient_account_3, chain, mtx));
197 CHECK_EQ(MK_COINS(16), get_balance(m_recipient_account_4, chain, mtx));
198
199 std::vector<transaction> tx_pool;
200 r = c.get_pool_transactions(tx_pool);
202 CHECK_EQ(1, tx_pool.size());
203 CHECK_TEST_CONDITION(!(tx_pool.front() == m_tx_pool.front()));
204
205 std::vector<size_t> tx_outs;
206 uint64_t transfered;
207 lookup_acc_outs(m_recipient_account_2.get_keys(), tx_pool.front(), tx_outs, transfered);
208 CHECK_EQ(MK_COINS(7), transfered);
209
210 return true;
211}
bool find_block_chain(const std::vector< test_event_entry > &events, std::vector< cryptonote::block > &blockchain, map_hash2tx_t &mtx, const crypto::hash &head)
uint64_t get_balance(const cryptonote::account_base &addr, const std::vector< cryptonote::block > &blockchain, const map_hash2tx_t &mtx)
Definition chaingen.cpp:940
#define MAKE_NEXT_BLOCK(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC)
Definition chaingen.h:839
#define REWIND_BLOCKS(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC)
Definition chaingen.h:890
#define DEFINE_TESTS_ERROR_CONTEXT(text)
Definition chaingen.h:1056
std::unordered_map< crypto::hash, const cryptonote::transaction * > map_hash2tx_t
Definition chaingen.h:163
#define CHECK_TEST_CONDITION(cond)
Definition chaingen.h:1057
#define MAKE_TX_LIST_START(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition chaingen.h:935
#define MAKE_GENESIS_BLOCK(VEC_EVENTS, BLK_NAME, MINER_ACC, TS)
Definition chaingen.h:833
#define MAKE_NEXT_BLOCK_TX_LIST(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST)
Definition chaingen.h:867
#define REGISTER_CALLBACK(CB_NAME, CLBACK)
Definition chaingen.h:827
#define DO_CALLBACK(VEC_EVENTS, CB_NAME)
Definition chaingen.h:820
#define MAKE_TX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD)
Definition chaingen.h:933
#define MK_COINS(amount)
Definition chaingen.h:1060
#define MAKE_ACCOUNT(VEC_EVENTS, account)
Definition chaingen.h:815
#define MAKE_TX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, HEAD)
Definition chaingen.h:903
#define GENERATE_ACCOUNT(account)
Definition chaingen.h:801
#define CHECK_EQ(v1, v2)
Definition chaingen.h:1058
#define MAKE_NEXT_BLOCK_TX1(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1)
Definition chaingen.h:849
handles core cryptonote functionality
size_t get_alternative_blocks_count() const
returns the number of alternative blocks stored
bool get_alternative_blocks(std::vector< block > &blocks) const
compiles a list of all blocks stored as alternative chains
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block > > &blocks, std::vector< cryptonote::blobdata > &txs) const
bool get_pool_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
bool check_split_switched(cryptonote::core &c, size_t ev_index, const std::vector< test_event_entry > &events)
bool generate(std::vector< test_event_entry > &events) const
bool check_split_not_switched(cryptonote::core &c, size_t ev_index, const std::vector< test_event_entry > &events)
#define CRYPTONOTE_MINED_ETN_UNLOCK_WINDOW
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
bool lookup_acc_outs(const account_keys &acc, const transaction &tx, std::vector< size_t > &outs, uint64_t &etn_transfered)
crypto::hash get_block_hash(uint64_t height)
unsigned __int64 uint64_t
Definition stdint.h:136