Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
test_trx_retry_db.cpp
Go to the documentation of this file.
1#define BOOST_TEST_MODULE transaction_retry
2#include <boost/test/included/unit_test.hpp>
3
5
7
12#include <sysio/chain/trace.hpp>
13#include <sysio/chain/name.hpp>
14
17#include <fc/mock_time.hpp>
18#include <fc/bitutil.hpp>
19
20#include <boost/asio.hpp>
21#include <boost/date_time/posix_time/posix_time.hpp>
22#include <boost/filesystem.hpp>
23#include <thread>
24#include <condition_variable>
25#include <deque>
26#include <memory>
27
28namespace sysio::test::detail {
29
30using namespace sysio::chain;
31using namespace sysio::chain::literals;
32
33struct testit {
35 testit( uint64_t id = 0 )
36 :id(id){}
37
39 return chain::config::system_account_name;
40 }
42 return "testit"_n;
43 }
44};
45
46} // sysio::test::detail
48
49namespace {
50
51using namespace sysio;
52using namespace sysio::chain;
53using namespace sysio::chain_apis;
54using namespace sysio::test::detail;
55
56// simple thread-safe queue
57template <typename T>
58class blocking_queue
59{
60public:
61 void push( T const& value ) {
62 {
63 std::unique_lock<std::mutex> lock( mtx );
64 queue.push_front( value );
65 }
66 cond_v.notify_one();
67 }
68
69 T pop() {
70 std::unique_lock<std::mutex> lock( mtx );
71 if( !cond_v.wait_for( lock, std::chrono::seconds( 10 ),
72 [&] { return !queue.empty(); } ) ){
73 throw std::runtime_error("timed out, nothing in queue");
74 }
75 T r( std::move( queue.back() ) );
76 queue.pop_back();
77 return r;
78 }
79
80 size_t size() const {
81 std::unique_lock<std::mutex> lock( mtx );
82 return queue.size();
83 }
84private:
85 mutable std::mutex mtx;
86 std::condition_variable cond_v;
87 std::deque<T> queue;
88};
89
90auto get_private_key( chain::name keyname, std::string role = "owner" ) {
91 auto secret = fc::sha256::hash( keyname.to_string() + role );
93}
94
95auto get_public_key( chain::name keyname, std::string role = "owner" ) {
96 return get_private_key( keyname, role ).get_public_key();
97}
98
99auto make_unique_trx( const chain_id_type& chain_id, const fc::microseconds& expiration, uint64_t id ) {
100
101 account_name creator = config::system_account_name;
103 trx.expiration = fc::time_point::now() + expiration;
104 trx.actions.emplace_back( vector<permission_level>{{creator, config::active_name}},
105 testit{ id } );
106 trx.sign( get_private_key("test"_n), chain_id );
107
108 return std::make_shared<packed_transaction>( std::move(trx), packed_transaction::compression_type::none);
109}
110
111chain::transaction_trace_ptr make_transaction_trace( const packed_transaction_ptr trx, uint32_t block_number,
113 return std::make_shared<chain::transaction_trace>(chain::transaction_trace{
114 trx->id(),
115 block_number,
117 trx->id(), // block_id, doesn't matter what it is for this test as long as it is set
120 0,
121 false,
122 {}, // actions
123 {},
124 {},
125 {},
126 {},
127 {}
128 });
129}
130
131uint64_t get_id( const transaction& trx ) {
132 testit t = trx.actions.at(0).data_as<testit>();
133 return t.id;
134}
135
136uint64_t get_id( const packed_transaction_ptr& ptr ) {
137 return get_id( ptr->get_transaction() );
138}
139
140auto make_block_state( uint32_t block_num, std::vector<chain::packed_transaction_ptr> trxs ) {
141 name producer = "kevinh"_n;
142 chain::signed_block_ptr block = std::make_shared<chain::signed_block>();
143 for( auto& trx : trxs ) {
144 block->transactions.emplace_back( *trx );
145 }
146 block->producer = producer;
147 block->timestamp = fc::time_point::now();
149 previous._hash[0] &= 0xffffffff00000000;
150 previous._hash[0] += fc::endian_reverse_u32(block_num - 1);
151
152 block->previous = previous;
153
154 auto priv_key = get_private_key( block->producer, "active" );
155 auto pub_key = get_public_key( block->producer, "active" );
156
157 auto prev = std::make_shared<chain::block_state>();
158 auto header_bmroot = chain::digest_type::hash( std::make_pair( block->digest(), prev->blockroot_merkle.get_root()));
159 auto sig_digest = chain::digest_type::hash( std::make_pair( header_bmroot, prev->pending_schedule.schedule_hash ));
160 block->producer_signature = priv_key.sign( sig_digest );
161
162 std::vector<chain::private_key_type> signing_keys;
163 signing_keys.emplace_back( priv_key );
164 auto signer = [&]( chain::digest_type d ) {
165 std::vector<chain::signature_type> result;
166 result.reserve( signing_keys.size());
167 for( const auto& k: signing_keys )
168 result.emplace_back( k.sign( d ));
169 return result;
170 };
172 pbhs.producer = block->producer;
173 pbhs.timestamp = block->timestamp;
174 pbhs.previous = block->previous;
176 {0, {chain::producer_authority{block->producer,
177 chain::block_signing_authority_v0{1, {{pub_key, 1}}}}}};
178 pbhs.active_schedule = schedule;
180 auto bsp = std::make_shared<chain::block_state>(
181 std::move( pbhs ),
182 std::move( block ),
183 std::vector<chain::transaction_metadata_ptr>(),
185 []( chain::block_timestamp_type timestamp,
186 const fc::flat_set<chain::digest_type>& cur_features,
187 const std::vector<chain::digest_type>& new_features ) {},
188 signer
189 );
190 bsp->block_num = block_num;
191
192 return bsp;
193}
194
195} // anonymous namespace
196
197BOOST_AUTO_TEST_SUITE(trx_retry_db_test)
198
199BOOST_AUTO_TEST_CASE(trx_retry_logic) {
200 boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
201
202 try {
204
205 // just need a controller for trx_retry_db, doesn't actually have to do anything
206 std::optional<controller> chain;
207 genesis_state gs{};
208 {
210 chain_config.blocks_dir = temp;
211 chain_config.state_dir = temp;
212
213 const auto& genesis_chain_id = gs.compute_chain_id();
215 chain.emplace( chain_config, std::move( pfs ), genesis_chain_id );
216 chain->add_indices();
217 }
218
219 // control time by using set_now, call before spawning any threads
220 auto pnow = boost::posix_time::time_from_string("2022-04-04 4:44:44.000");
222
223 // run app() so that channels::transaction_ack work
224 std::thread app_thread( [&]() {
225 appbase::app().exec();
226 } );
227
228 size_t max_mem_usage_size = 5ul*1024*1024*1024;
229 fc::microseconds retry_interval = fc::seconds(10);
230 boost::posix_time::seconds pretry_interval = boost::posix_time::seconds(10);
231 BOOST_REQUIRE(retry_interval.count() == pretry_interval.total_microseconds());
232 fc::microseconds max_expiration_time = fc::hours(1);
233 trx_retry_db trx_retry( *chain, max_mem_usage_size, retry_interval, max_expiration_time, fc::seconds(10) );
234
235 // provide a subscriber for the transaction_ack channel
236 blocking_queue<std::pair<fc::exception_ptr, packed_transaction_ptr>> transactions_acked;
237 plugin_interface::compat::channels::transaction_ack::channel_type::handle incoming_transaction_ack_subscription =
239 [&transactions_acked]( const std::pair<fc::exception_ptr, packed_transaction_ptr>& t){
240 transactions_acked.push( t );
241 } );
242
243
244 // test get_max_expiration_time
245 BOOST_CHECK( fc::time_point::now() + fc::hours(1) == fc::time_point( trx_retry.get_max_expiration_time() ) );
246
247 //
248 // test expired, not in a block
249 //
250 auto lib = std::optional<uint16_t>{};
251 auto trx_1 = make_unique_trx(chain->get_chain_id(), fc::seconds(2), 1);
252 bool trx_1_expired = false;
253 trx_retry.track_transaction( trx_1, lib, [&trx_1_expired](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
254 BOOST_REQUIRE( std::holds_alternative<fc::exception_ptr>(result) );
255 BOOST_CHECK_EQUAL( std::get<fc::exception_ptr>(result)->code(), expired_tx_exception::code_value );
256 trx_1_expired = true;
257 } );
258 auto trx_2 = make_unique_trx(chain->get_chain_id(), fc::seconds(4), 2);
259 bool trx_2_expired = false;
260 trx_retry.track_transaction( trx_2, lib, [&trx_2_expired](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
261 BOOST_REQUIRE( std::holds_alternative<fc::exception_ptr>(result) );
262 BOOST_CHECK_EQUAL( std::get<fc::exception_ptr>(result)->code(), expired_tx_exception::code_value );
263 trx_2_expired = true;
264 } );
265 // signal block, nothing should be expired as now has not changed
266 auto bsp1 = make_block_state(1, {});
267 trx_retry.on_block_start(1);
268 trx_retry.on_accepted_block(bsp1);
269 trx_retry.on_irreversible_block(bsp1);
270 BOOST_CHECK(!trx_1_expired);
271 BOOST_CHECK(!trx_2_expired);
272 // increase time by 3 seconds to expire first
273 pnow += boost::posix_time::seconds(3);
275 // signal block, first transaction should expire
276 auto bsp2 = make_block_state(2, {});
277 trx_retry.on_block_start(2);
278 trx_retry.on_accepted_block(bsp2);
279 trx_retry.on_irreversible_block(bsp2);
280 BOOST_CHECK(trx_1_expired);
281 BOOST_CHECK(!trx_2_expired);
282 // increase time by 2 seconds to expire second
283 pnow += boost::posix_time::seconds(2);
285 // signal block, second transaction should expire
286 auto bsp3 = make_block_state(3, {});
287 trx_retry.on_block_start(3);
288 trx_retry.on_accepted_block(bsp3);
289 trx_retry.on_irreversible_block(bsp3);
290 BOOST_CHECK(trx_1_expired);
291 BOOST_CHECK(trx_2_expired);
292 BOOST_CHECK_EQUAL(0, trx_retry.size());
293
294 //
295 // test resend trx if not in block
296 //
297 auto trx_3 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 3);
298 bool trx_3_expired = false;
299 trx_retry.track_transaction( trx_3, lib, [&trx_3_expired](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
300 BOOST_REQUIRE( std::holds_alternative<fc::exception_ptr>(result) );
301 BOOST_CHECK_EQUAL( std::get<fc::exception_ptr>(result)->code(), expired_tx_exception::code_value );
302 trx_3_expired = true;
303 } );
304 // increase time by 1 seconds, so trx_4 retry interval diff than 3
305 pnow += boost::posix_time::seconds(1);
307 auto trx_4 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 4);
308 bool trx_4_expired = false;
309 trx_retry.track_transaction( trx_4, lib, [&trx_4_expired](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
310 BOOST_REQUIRE( std::holds_alternative<fc::exception_ptr>(result) );
311 BOOST_CHECK_EQUAL( std::get<fc::exception_ptr>(result)->code(), expired_tx_exception::code_value );
312 trx_4_expired = true;
313 } );
314 // increase time by interval to cause send
315 pnow += (pretry_interval - boost::posix_time::seconds(1));
317 // signal block, transaction 3 should be sent
318 auto bsp4 = make_block_state(4, {});
319 trx_retry.on_block_start(4);
320 trx_retry.on_accepted_block(bsp4);
321 BOOST_CHECK( get_id(transactions_acked.pop().second) == 3 );
322 BOOST_CHECK_EQUAL( 0, transactions_acked.size() );
323 // increase time by 1 seconds, so trx_4 is sent
324 pnow += boost::posix_time::seconds(1);
326 // signal block, transaction 4 should be sent
327 auto bsp5 = make_block_state(5, {});
328 trx_retry.on_block_start(5);
329 trx_retry.on_accepted_block(bsp5);
330 BOOST_CHECK( get_id(transactions_acked.pop().second) == 4 );
331 BOOST_CHECK_EQUAL( 0, transactions_acked.size() );
332 BOOST_CHECK(!trx_3_expired);
333 BOOST_CHECK(!trx_4_expired);
334 // go ahead and expire them now
335 pnow += boost::posix_time::seconds(30);
337 auto bsp6 = make_block_state(6, {});
338 trx_retry.on_block_start(6);
339 trx_retry.on_accepted_block(bsp6);
340 trx_retry.on_irreversible_block(bsp4);
341 trx_retry.on_irreversible_block(bsp5);
342 trx_retry.on_irreversible_block(bsp6);
343 BOOST_CHECK(trx_3_expired);
344 BOOST_CHECK(trx_4_expired);
345 BOOST_CHECK_EQUAL(0, trx_retry.size());
346
347 //
348 // test reply to user
349 //
350 auto trx_5 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 5);
351 bool trx_5_variant = false;
352 trx_retry.track_transaction( trx_5, lib, [&trx_5_variant](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
353 BOOST_REQUIRE( std::holds_alternative<std::unique_ptr<fc::variant>>(result) );
354 BOOST_CHECK( !!std::get<std::unique_ptr<fc::variant>>(result) );
355 trx_5_variant = true;
356 } );
357 // increase time by 1 seconds, so trx_6 retry interval diff than 5
358 pnow += boost::posix_time::seconds(1);
360 auto trx_6 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 6);
361 bool trx_6_variant = false;
362 trx_retry.track_transaction( trx_6, std::optional<uint32_t>(2), [&trx_6_variant](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
363 BOOST_REQUIRE( std::holds_alternative<std::unique_ptr<fc::variant>>(result) );
364 BOOST_CHECK( !!std::get<std::unique_ptr<fc::variant>>(result) );
365 trx_6_variant = true;
366 } );
367 // not in block 7, so not returned to user
368 auto bsp7 = make_block_state(7, {});
369 trx_retry.on_block_start(7);
370 trx_retry.on_accepted_block(bsp7);
371 BOOST_CHECK(!trx_5_variant);
372 BOOST_CHECK(!trx_6_variant);
373 // 5,6 in block 8
374 pnow += boost::posix_time::seconds(1); // new block, new time
376 trx_retry.on_block_start(8);
377 auto trace_5 = make_transaction_trace( trx_5, 8);
378 auto trace_6 = make_transaction_trace( trx_6, 8);
379 trx_retry.on_applied_transaction(trace_5, trx_5);
380 trx_retry.on_applied_transaction(trace_6, trx_6);
381 auto bsp8 = make_block_state(8, {trx_5, trx_6});
382 trx_retry.on_accepted_block(bsp8);
383 BOOST_CHECK(!trx_5_variant);
384 BOOST_CHECK(!trx_6_variant);
385 // need 2 blocks before 6 returned to user
386 pnow += boost::posix_time::seconds(1); // new block, new time
388 auto bsp9 = make_block_state(9, {});
389 trx_retry.on_block_start(9);
390 trx_retry.on_accepted_block(bsp9);
391 BOOST_CHECK(!trx_5_variant);
392 BOOST_CHECK(!trx_6_variant);
393 pnow += boost::posix_time::seconds(1); // new block, new time
395 auto bsp10 = make_block_state(10, {});
396 trx_retry.on_block_start(10);
397 trx_retry.on_accepted_block(bsp10);
398 BOOST_CHECK(!trx_5_variant);
399 BOOST_CHECK(trx_6_variant);
400 // now signal lib for trx_6
401 pnow += boost::posix_time::seconds(1); // new block, new time
403 auto bsp11 = make_block_state(11, {});
404 trx_retry.on_block_start(11);
405 trx_retry.on_accepted_block(bsp11);
406 BOOST_CHECK(!trx_5_variant);
407 BOOST_CHECK(trx_6_variant);
408 trx_retry.on_irreversible_block(bsp7);
409 BOOST_CHECK(!trx_5_variant);
410 BOOST_CHECK(trx_6_variant);
411 trx_retry.on_irreversible_block(bsp8);
412 BOOST_CHECK(trx_5_variant);
413 BOOST_CHECK(trx_6_variant);
414 BOOST_CHECK_EQUAL(0, trx_retry.size());
415
416 //
417 // test forking
418 //
419 auto trx_7 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 7);
420 bool trx_7_variant = false;
421 trx_retry.track_transaction( trx_7, lib, [&trx_7_variant](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
422 BOOST_REQUIRE( std::holds_alternative<std::unique_ptr<fc::variant>>(result) );
423 BOOST_CHECK( !!std::get<std::unique_ptr<fc::variant>>(result) );
424 trx_7_variant = true;
425 } );
426 // increase time by 1 seconds, so trx_8 retry interval diff than 7
427 pnow += boost::posix_time::seconds(1);
429 auto trx_8 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 8);
430 bool trx_8_variant = false;
431 trx_retry.track_transaction( trx_8, std::optional<uint32_t>(3), [&trx_8_variant](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
432 BOOST_REQUIRE( std::holds_alternative<std::unique_ptr<fc::variant>>(result) );
433 BOOST_CHECK( !!std::get<std::unique_ptr<fc::variant>>(result) );
434 trx_8_variant = true;
435 } );
436 // one to expire, will be forked out never to return
437 auto trx_9 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 9);
438 bool trx_9_expired = false;
439 trx_retry.track_transaction( trx_9, lib, [&trx_9_expired](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
440 BOOST_REQUIRE( std::holds_alternative<fc::exception_ptr>(result) );
441 BOOST_CHECK_EQUAL( std::get<fc::exception_ptr>(result)->code(), expired_tx_exception::code_value );
442 trx_9_expired = true;
443 } );
444
445 // not in block 12
446 auto bsp12 = make_block_state(12, {});
447 trx_retry.on_block_start(12);
448 trx_retry.on_accepted_block(bsp12);
449 BOOST_CHECK(!trx_7_variant);
450 BOOST_CHECK(!trx_8_variant);
451 BOOST_CHECK(!trx_9_expired);
452 // 7,8 in block 13
453 pnow += boost::posix_time::seconds(1); // new block, new time
455 trx_retry.on_block_start(13);
456 auto trace_7 = make_transaction_trace( trx_7, 13);
457 auto trace_8 = make_transaction_trace( trx_8, 13);
458 auto trace_9 = make_transaction_trace( trx_9, 13);
459 trx_retry.on_applied_transaction(trace_7, trx_7);
460 trx_retry.on_applied_transaction(trace_8, trx_8);
461 trx_retry.on_applied_transaction(trace_9, trx_9);
462 auto bsp13 = make_block_state(13, {trx_7, trx_8, trx_9});
463 trx_retry.on_accepted_block(bsp13);
464 BOOST_CHECK(!trx_7_variant);
465 BOOST_CHECK(!trx_8_variant);
466 BOOST_CHECK(!trx_9_expired);
467 // need 3 blocks before 8 returned to user
468 pnow += boost::posix_time::seconds(1); // new block, new time, 1st block
470 auto bsp14 = make_block_state(14, {});
471 trx_retry.on_block_start(14);
472 trx_retry.on_accepted_block(bsp14);
473 BOOST_CHECK(!trx_7_variant);
474 BOOST_CHECK(!trx_8_variant);
475 BOOST_CHECK(!trx_9_expired);
476 pnow += boost::posix_time::seconds(1); // new block, new time, 2nd block
478 auto bsp15 = make_block_state(15, {});
479 trx_retry.on_block_start(15);
480 trx_retry.on_accepted_block(bsp15);
481 BOOST_CHECK(!trx_7_variant);
482 BOOST_CHECK(!trx_8_variant);
483 BOOST_CHECK(!trx_9_expired);
484 // now fork out including 13 which had traces, trx_9 will be forked out and not re-appear
485 pnow += boost::posix_time::seconds(1); // new block, new time
487 trx_retry.on_block_start(13);
488 // should still be tracking them
489 BOOST_CHECK_EQUAL(3, trx_retry.size());
490 // now produce an empty 13
491 auto bsp13b = make_block_state(13, {}); // now 13 has no traces
492 trx_retry.on_accepted_block(bsp13b);
493 // produced another empty block
494 pnow += boost::posix_time::seconds(1); // new block, new time
496 trx_retry.on_block_start(14);
497 // now produce an empty 14
498 auto bsp14b = make_block_state(14, {}); // empty
499 trx_retry.on_accepted_block(bsp14b);
500 // produce block with 7,8
501 trx_retry.on_block_start(15);
502 auto trace_7b = make_transaction_trace( trx_7, 15);
503 auto trace_8b = make_transaction_trace( trx_8, 15);
504 trx_retry.on_applied_transaction(trace_7b, trx_7);
505 trx_retry.on_applied_transaction(trace_8b, trx_8);
506 auto bsp15b = make_block_state(15, {trx_7, trx_8});
507 trx_retry.on_accepted_block(bsp15b);
508 // need 3 blocks before 8 returned to user
509 pnow += boost::posix_time::seconds(1); // new block, new time
511 auto bsp16 = make_block_state(16, {});
512 trx_retry.on_block_start(16);
513 trx_retry.on_accepted_block(bsp16);
514 BOOST_CHECK(!trx_7_variant);
515 BOOST_CHECK(!trx_8_variant);
516 BOOST_CHECK(!trx_9_expired);
517 pnow += boost::posix_time::seconds(1); // new block, new time
519 auto bsp17 = make_block_state(17, {});
520 trx_retry.on_block_start(17);
521 trx_retry.on_accepted_block(bsp17);
522 BOOST_CHECK(!trx_7_variant);
523 BOOST_CHECK(!trx_8_variant);
524 BOOST_CHECK(!trx_9_expired);
525 pnow += boost::posix_time::seconds(1); // new block, new time, 3rd one
527 auto bsp18 = make_block_state(18, {});
528 trx_retry.on_block_start(18);
529 trx_retry.on_accepted_block(bsp18);
530 BOOST_CHECK(!trx_7_variant);
531 BOOST_CHECK(trx_8_variant);
532 BOOST_CHECK(!trx_9_expired);
533 trx_retry.on_irreversible_block(bsp9);
534 trx_retry.on_irreversible_block(bsp10);
535 trx_retry.on_irreversible_block(bsp11);
536 trx_retry.on_irreversible_block(bsp12);
537 trx_retry.on_irreversible_block(bsp13b);
538 trx_retry.on_irreversible_block(bsp14b);
539 BOOST_CHECK(!trx_7_variant);
540 BOOST_CHECK(trx_8_variant);
541 BOOST_CHECK(!trx_9_expired);
542 trx_retry.on_irreversible_block(bsp15b);
543 BOOST_CHECK(trx_7_variant);
544 BOOST_CHECK(trx_8_variant);
545 BOOST_CHECK(!trx_9_expired);
546 // verify trx_9 expires
547 pnow += boost::posix_time::seconds(21); // new block, new time, before expire
549 auto bsp19 = make_block_state(19, {});
550 trx_retry.on_block_start(19);
551 trx_retry.on_accepted_block(bsp19);
552 trx_retry.on_irreversible_block(bsp15);
553 trx_retry.on_irreversible_block(bsp16);
554 trx_retry.on_irreversible_block(bsp17);
555 trx_retry.on_irreversible_block(bsp18);
556 trx_retry.on_irreversible_block(bsp19);
557 BOOST_CHECK(trx_7_variant);
558 BOOST_CHECK(trx_8_variant);
559 BOOST_CHECK(!trx_9_expired);
560 pnow += boost::posix_time::seconds(1); // new block, new time, trx_9 now expired
562 auto bsp20 = make_block_state(20, {});
563 trx_retry.on_block_start(20);
564 trx_retry.on_accepted_block(bsp20);
565 // waits for LIB
566 BOOST_CHECK(trx_7_variant);
567 BOOST_CHECK(trx_8_variant);
568 BOOST_CHECK(!trx_9_expired);
569 trx_retry.on_irreversible_block(bsp20);
570 BOOST_CHECK(trx_7_variant);
571 BOOST_CHECK(trx_8_variant);
572 BOOST_CHECK(trx_9_expired);
573 BOOST_CHECK_EQUAL(0, trx_retry.size());
574
575 //
576 // test reply to user for num_blocks == 0
577 //
578 auto trx_10 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 10);
579 bool trx_10_variant = false;
580 trx_retry.track_transaction( trx_10, std::optional<uint32_t>(0), [&trx_10_variant](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
581 BOOST_REQUIRE( std::holds_alternative<std::unique_ptr<fc::variant>>(result) );
582 BOOST_CHECK( !!std::get<std::unique_ptr<fc::variant>>(result) );
583 trx_10_variant = true;
584 } );
585 auto trx_11 = make_unique_trx(chain->get_chain_id(), fc::seconds(30), 11);
586 bool trx_11_variant = false;
587 trx_retry.track_transaction( trx_11, std::optional<uint32_t>(1), [&trx_11_variant](const std::variant<fc::exception_ptr, std::unique_ptr<fc::variant>>& result){
588 BOOST_REQUIRE( std::holds_alternative<std::unique_ptr<fc::variant>>(result) );
589 BOOST_CHECK( !!std::get<std::unique_ptr<fc::variant>>(result) );
590 trx_11_variant = true;
591 } );
592 // seen in block immediately
593 trx_retry.on_block_start(21);
594 auto trace_10 = make_transaction_trace( trx_10, 21);
595 auto trace_11 = make_transaction_trace( trx_11, 21);
596 trx_retry.on_applied_transaction(trace_10, trx_10);
597 trx_retry.on_applied_transaction(trace_11, trx_11);
598 auto bsp21 = make_block_state(21, {trx_10, trx_11});
599 trx_retry.on_accepted_block(bsp21);
600 BOOST_CHECK(trx_10_variant);
601 BOOST_CHECK(!trx_11_variant);
602 pnow += boost::posix_time::seconds(1); // new block, new time
604 auto bsp22 = make_block_state(22, {});
605 trx_retry.on_block_start(22);
606 trx_retry.on_accepted_block(bsp22);
607 BOOST_CHECK(trx_10_variant);
608 BOOST_CHECK(trx_11_variant);
609 BOOST_CHECK_EQUAL(0, trx_retry.size());
610
611
612 // shutdown
613 appbase::app().quit();
614 app_thread.join();
615
616 } catch ( ... ) {
617 boost::filesystem::remove_all( temp );
618 throw;
619 }
620 boost::filesystem::remove_all( temp );
621}
622
623
624BOOST_AUTO_TEST_SUITE_END()
const mie::Vuint & r
Definition bn.cpp:28
auto get_channel() -> std::enable_if_t< is_channel_decl< ChannelDecl >::value, typename ChannelDecl::channel_type & >
static private_key regenerate(const typename KeyType::data_type &data)
logger & set_log_level(log_level e)
Definition logger.cpp:100
static logger get(const fc::string &name=DEFAULT_LOGGER)
Definition logger.cpp:88
constexpr int64_t count() const
Definition time.hpp:26
static void set_now(time_type t)
Definition mock_time.cpp:14
static sha256 hash(const char *d, uint32_t dlen)
Definition sha256.cpp:44
static time_point now()
Definition time.cpp:14
void on_applied_transaction(const chain::transaction_trace_ptr &trace, const chain::packed_transaction_ptr &ptrx)
fc::time_point_sec get_max_expiration_time() const
void on_irreversible_block(const chain::block_state_ptr &block)
void track_transaction(chain::packed_transaction_ptr ptrx, std::optional< uint16_t > num_blocks, next_function< std::unique_ptr< fc::variant > > next)
void on_accepted_block(const chain::block_state_ptr &block)
void on_block_start(uint32_t block_num)
#define DEFAULT_LOGGER
Definition logger.hpp:7
application & app()
std::shared_ptr< exception > exception_ptr
constexpr microseconds hours(int64_t h)
Definition time.hpp:35
constexpr microseconds seconds(int64_t s)
Definition time.hpp:32
uint32_t endian_reverse_u32(uint32_t x)
Definition bitutil.hpp:19
std::shared_ptr< transaction_trace > transaction_trace_ptr
Definition trace.hpp:20
std::shared_ptr< const packed_transaction > packed_transaction_ptr
sysio::chain::action_name action_name
std::shared_ptr< signed_block > signed_block_ptr
Definition block.hpp:105
auto get_private_key(chain::name keyname, std::string role="owner")
auto make_block_state(chain::block_id_type previous, uint32_t height, uint32_t slot, chain::name producer, std::vector< chain::packed_transaction > trxs)
auto get_public_key(chain::name keyname, std::string role="owner")
uint32_t previous(octet_iterator &it, octet_iterator pass_start)
Deprecated in versions that include "prior".
Definition checked.h:179
#define value
Definition pkcs11.h:157
#define T(meth, val, expected)
#define FC_REFLECT(TYPE, MEMBERS)
Specializes fc::reflector for TYPE.
Definition reflect.hpp:311
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
v1 Producer-voted blockchain configuration parameters
Immutable except for fc::from_variant.
Definition name.hpp:43
std::string to_string() const
Definition name.cpp:19
const signature_type & sign(const private_key_type &key, const chain_id_type &chain_id)
time_point_sec expiration
the time at which a transaction expires
@ executed
succeed, no error handler executed
Definition block.hpp:14
vector< action > actions
static account_name get_account()
BOOST_AUTO_TEST_CASE(trx_retry_logic)
void lock()
CK_ULONG d