Electroneum
Loading...
Searching...
No Matches
transactions_flow_test.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool transactions_flow_test (std::string &working_folder, std::string path_source_wallet, std::string path_target_wallet, std::string &daemon_addr_a, std::string &daemon_addr_b, uint64_t amount_to_transfer, size_t mix_in_factor, size_t transactions_count, size_t transactions_per_second)

Function Documentation

◆ transactions_flow_test()

bool transactions_flow_test ( std::string & working_folder,
std::string path_source_wallet,
std::string path_target_wallet,
std::string & daemon_addr_a,
std::string & daemon_addr_b,
uint64_t amount_to_transfer,
size_t mix_in_factor,
size_t transactions_count,
size_t transactions_per_second )

Definition at line 115 of file transactions_flow_test.cpp.

121{
122 LOG_PRINT_L0("-----------------------STARTING TRANSACTIONS FLOW TEST-----------------------");
123 tools::wallet2 w1, w2;
124 if(path_source_wallet.empty())
125 path_source_wallet = generate_random_wallet_name();
126
127 if(path_target_wallet.empty())
128 path_target_wallet = generate_random_wallet_name();
129
130
131 try
132 {
133 w1.generate(working_folder + "/" + path_source_wallet, "");
134 w2.generate(working_folder + "/" + path_target_wallet, "");
135 }
136 catch (const std::exception& e)
137 {
138 LOG_ERROR("failed to generate wallet: " << e.what());
139 return false;
140 }
141
142 w1.init(daemon_addr_a);
143
144 uint64_t blocks_fetched = 0;
145 bool received_etn;
146 bool ok;
147 if(!w1.refresh(true, blocks_fetched, received_etn, ok))
148 {
149 LOG_ERROR( "failed to refresh source wallet from " << daemon_addr_a );
150 return false;
151 }
152
153 w2.init(daemon_addr_b);
154
155 MGINFO_GREEN("Using wallets: " << ENDL
156 << "Source: " << w1.get_account().get_public_address_str(MAINNET) << ENDL << "Path: " << working_folder + "/" + path_source_wallet << ENDL
157 << "Target: " << w2.get_account().get_public_address_str(MAINNET) << ENDL << "Path: " << working_folder + "/" + path_target_wallet);
158
159 //lets do some etn
161 COMMAND_RPC_STOP_MINING::request daemon1_req = AUTO_VAL_INIT(daemon1_req);
162 COMMAND_RPC_STOP_MINING::response daemon1_rsp = AUTO_VAL_INIT(daemon1_rsp);
163 bool r = http_client.set_server(daemon_addr_a, boost::none) && net_utils::invoke_http_json("/stop_mine", daemon1_req, daemon1_rsp, http_client, std::chrono::seconds(10));
164 CHECK_AND_ASSERT_MES(r, false, "failed to stop mining");
165
166 COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req);
167 COMMAND_RPC_START_MINING::response daemon_rsp = AUTO_VAL_INIT(daemon_rsp);
168 daemon_req.miner_address = w1.get_account().get_public_address_str(MAINNET);
169 daemon_req.threads_count = 9;
170 r = net_utils::invoke_http_json("/start_mining", daemon_req, daemon_rsp, http_client, std::chrono::seconds(10));
171 CHECK_AND_ASSERT_MES(r, false, "failed to start mining getrandom_outs");
172 CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to start mining");
173
174 //wait for etn, until balance will have enough etn
175 w1.refresh(true, blocks_fetched, received_etn, ok);
176 while(w1.unlocked_balance(0, false) < amount_to_transfer)
177 {
179 w1.refresh(true, blocks_fetched, received_etn, ok);
180 }
181
182 //lets make a lot of small outs to ourselves
183 //since it is not possible to start from transaction that bigger than 20Kb, we gonna make transactions
184 //with 500 outs (about 18kb), and we have to wait appropriate count blocks, mined for test wallet
185 while(true)
186 {
187 tools::wallet2::transfer_container incoming_transfers;
188 w1.get_transfers(incoming_transfers);
189 if(incoming_transfers.size() > FIRST_N_TRANSFERS && get_etn_in_first_transfers(incoming_transfers, FIRST_N_TRANSFERS) < w1.unlocked_balance(0, false) )
190 {
191 //lets go!
192 size_t count = 0;
193 BOOST_FOREACH(tools::wallet2::transfer_details& td, incoming_transfers)
194 {
196 bool r = do_send_etn(w1, w1, 0, td.m_tx.vout[td.m_internal_output_index].amount - TEST_FEE, tx_s, 50);
197 CHECK_AND_ASSERT_MES(r, false, "Failed to send starter tx " << get_transaction_hash(tx_s));
198 MGINFO_GREEN("Starter transaction sent " << get_transaction_hash(tx_s));
199 if(++count >= FIRST_N_TRANSFERS)
200 break;
201 }
202 break;
203 }else
204 {
206 w1.refresh(true, blocks_fetched, received_etn, ok);
207 }
208 }
209 //do actual transfer
210 uint64_t transfered_etn = 0;
211 uint64_t transfer_size = amount_to_transfer/transactions_count;
212 size_t i = 0;
213 struct tx_test_entry
214 {
215 transaction tx;
216 size_t m_received_count;
217 uint64_t amount_transfered;
218 };
219 crypto::key_image lst_sent_ki = AUTO_VAL_INIT(lst_sent_ki);
220 std::unordered_map<crypto::hash, tx_test_entry> txs;
221 for(i = 0; i != transactions_count; i++)
222 {
223 uint64_t amount_to_tx = (amount_to_transfer - transfered_etn) > transfer_size ? transfer_size: (amount_to_transfer - transfered_etn);
224 while(w1.unlocked_balance(0, false) < amount_to_tx + TEST_FEE)
225 {
226 misc_utils::sleep_no_w(1000);
227 LOG_PRINT_L0("not enough ETN, waiting for cashback or mining");
228 w1.refresh(true, blocks_fetched, received_etn, ok);
229 }
230
231 transaction tx;
232 /*size_t n_attempts = 0;
233 while (!do_send_etn(w1, w2, mix_in_factor, amount_to_tx, tx)) {
234 n_attempts++;
235 std::cout << "failed to transfer ETN, refresh and try again (attempts=" << n_attempts << ")" << std::endl;
236 w1.refresh();
237 }*/
238
239
240 if(!do_send_etn(w1, w2, mix_in_factor, amount_to_tx, tx))
241 {
242 LOG_PRINT_L0("failed to transfer ETN, tx: " << get_transaction_hash(tx) << ", refresh and try again" );
243 w1.refresh(true, blocks_fetched, received_etn, ok);
244 if(!do_send_etn(w1, w2, mix_in_factor, amount_to_tx, tx))
245 {
246 LOG_PRINT_L0( "failed to transfer ETN, second chance. tx: " << get_transaction_hash(tx) << ", exit" );
247 LOCAL_ASSERT(false);
248 return false;
249 }
250 }
251 lst_sent_ki = boost::get<txin_to_key>(tx.vin[0]).k_image;
252
253 transfered_etn += amount_to_tx;
254
255 LOG_PRINT_L0("transferred " << amount_to_tx << ", i=" << i );
256 tx_test_entry& ent = txs[get_transaction_hash(tx)] = boost::value_initialized<tx_test_entry>();
257 ent.amount_transfered = amount_to_tx;
258 ent.tx = tx;
259 //if(i % transactions_per_second)
260 // misc_utils::sleep_no_w(1000);
261 }
262
263
264 LOG_PRINT_L0( "waiting some new blocks...");
265 misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*20*1000);//wait two blocks before sync on another wallet on another daemon
266 LOG_PRINT_L0( "refreshing...");
267 bool recvd_etn = false;
268 while(w2.refresh(true, blocks_fetched, recvd_etn, ok) && ( (blocks_fetched && recvd_etn) || !blocks_fetched ) )
269 {
270 misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*1000);//wait two blocks before sync on another wallet on another daemon
271 }
272
273 uint64_t etn_2 = w2.balance(0, false);
274 if(etn_2 == transfered_etn)
275 {
276 MGINFO_GREEN("-----------------------FINISHING TRANSACTIONS FLOW TEST OK-----------------------");
277 MGINFO_GREEN("transferred " << print_etn(transfered_etn) << " via " << i << " transactions" );
278 return true;
279 }else
280 {
282 w2.get_transfers(tc);
283 BOOST_FOREACH(tools::wallet2::transfer_details& td, tc)
284 {
285 auto it = txs.find(td.m_txid);
286 CHECK_AND_ASSERT_MES(it != txs.end(), false, "transaction not found in local cache");
287 it->second.m_received_count += 1;
288 }
289
290 BOOST_FOREACH(auto& tx_pair, txs)
291 {
292 if(tx_pair.second.m_received_count != 1)
293 {
294 MERROR("Transaction lost: " << get_transaction_hash(tx_pair.second.tx));
295 }
296
297 }
298
299 MERROR("-----------------------FINISHING TRANSACTIONS FLOW TEST FAILED-----------------------" );
300 MERROR("income " << print_etn(etn_2) << " via " << i << " transactions, expected ETN = " << print_etn(transfered_etn) );
301 LOCAL_ASSERT(false);
302 return false;
303 }
304
305 return true;
306}
std::string get_public_address_str(network_type nettype) const
Definition account.cpp:269
bool set_server(const std::string &address, boost::optional< login > user, ssl_options_t ssl_options=ssl_support_t::e_ssl_support_autodetect)
void refresh(bool trusted_daemon)
Definition wallet2.cpp:3060
cryptonote::account_base & get_account()
Definition wallet2.h:734
bool init(std::string daemon_address="http://localhost:8080", boost::optional< epee::net_utils::http::login > daemon_login=boost::none, boost::asio::ip::tcp::endpoint proxy={}, uint64_t upper_transaction_weight_limit=0, bool trusted_daemon=true, epee::net_utils::ssl_options_t ssl_options=epee::net_utils::ssl_support_t::e_ssl_support_autodetect, std::string blockchain_db_path="")
Definition wallet2.cpp:1282
void get_transfers(wallet2::transfer_container &incoming_transfers) const
Definition wallet2.cpp:6315
std::vector< transfer_details > transfer_container
Definition wallet2.h:449
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
Definition wallet2.cpp:6172
void generate(const std::string &wallet_, const epee::wipeable_string &password, const epee::wipeable_string &multisig_data, bool create_address_file=false)
Generates a wallet or restores one.
Definition wallet2.cpp:4869
uint64_t balance(uint32_t subaddr_index_major, bool public_blockchain) const
Definition wallet2.cpp:6162
#define CORE_RPC_STATUS_OK
#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN
#define AUTO_VAL_INIT(v)
#define MERROR(x)
Definition misc_log_ex.h:73
#define MGINFO_GREEN(x)
Definition misc_log_ex.h:82
#define LOCAL_ASSERT(expr)
#define ENDL
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
#define LOG_PRINT_L0(x)
Definition misc_log_ex.h:99
POD_CLASS key_image
Definition crypto.h:105
crypto::hash get_transaction_hash(const transaction &t)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool sleep_no_w(long ms)
http_simple_client_template< blocked_mode_client > http_simple_client
bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref method="GET")
mdb_size_t count(MDB_cursor *cur)
unsigned __int64 uint64_t
Definition stdint.h:136
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
cryptonote::transaction_prefix m_tx
Definition wallet2.h:304
#define FIRST_N_TRANSFERS
std::string generate_random_wallet_name()
bool do_send_etn(tools::wallet2 &w1, tools::wallet2 &w2, size_t mix_in_factor, uint64_t amount_to_transfer, transaction &tx, size_t parts=1)
uint64_t get_etn_in_first_transfers(const tools::wallet2::transfer_container &incoming_transfers, size_t n_transfers)
Here is the call graph for this function:
Here is the caller graph for this function: