199 {
200 boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
201
202 try {
204
205
206 std::optional<controller> chain;
208 {
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
220 auto pnow = boost::posix_time::time_from_string("2022-04-04 4:44:44.000");
222
223
224 std::thread app_thread( [&]() {
226 } );
227
228 size_t max_mem_usage_size = 5ul*1024*1024*1024;
230 boost::posix_time::seconds pretry_interval = boost::posix_time::seconds(10);
231 BOOST_REQUIRE(retry_interval.
count() == pretry_interval.total_microseconds());
234
235
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
246
247
248
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
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
273 pnow += boost::posix_time::seconds(3);
275
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
283 pnow += boost::posix_time::seconds(2);
285
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
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
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
315 pnow += (pretry_interval - boost::posix_time::seconds(1));
317
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
324 pnow += boost::posix_time::seconds(1);
326
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
335 pnow += boost::posix_time::seconds(30);
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
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
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
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
374 pnow += boost::posix_time::seconds(1);
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);
382 trx_retry.on_accepted_block(bsp8);
383 BOOST_CHECK(!trx_5_variant);
384 BOOST_CHECK(!trx_6_variant);
385
386 pnow += boost::posix_time::seconds(1);
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);
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
401 pnow += boost::posix_time::seconds(1);
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
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
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
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
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
453 pnow += boost::posix_time::seconds(1);
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);
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
468 pnow += boost::posix_time::seconds(1);
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);
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
485 pnow += boost::posix_time::seconds(1);
487 trx_retry.on_block_start(13);
488
489 BOOST_CHECK_EQUAL(3, trx_retry.size());
490
492 trx_retry.on_accepted_block(bsp13b);
493
494 pnow += boost::posix_time::seconds(1);
496 trx_retry.on_block_start(14);
497
499 trx_retry.on_accepted_block(bsp14b);
500
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);
507 trx_retry.on_accepted_block(bsp15b);
508
509 pnow += boost::posix_time::seconds(1);
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);
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);
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
547 pnow += boost::posix_time::seconds(21);
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);
563 trx_retry.on_block_start(20);
564 trx_retry.on_accepted_block(bsp20);
565
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
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
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);
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);
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
614 app_thread.join();
615
616 } catch ( ... ) {
617 boost::filesystem::remove_all( temp );
618 throw;
619 }
620 boost::filesystem::remove_all( temp );
621}
auto get_channel() -> std::enable_if_t< is_channel_decl< ChannelDecl >::value, typename ChannelDecl::channel_type & >
logger & set_log_level(log_level e)
static logger get(const fc::string &name=DEFAULT_LOGGER)
constexpr int64_t count() const
static void set_now(time_type t)
static const Segment gs(Segment::gs)
std::shared_ptr< exception > exception_ptr
constexpr microseconds hours(int64_t h)
constexpr microseconds seconds(int64_t s)
auto make_block_state(chain::block_id_type previous, uint32_t height, uint32_t slot, chain::name producer, std::vector< chain::packed_transaction > trxs)
v1 Producer-voted blockchain configuration parameters