diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 66126dbf5..2650d47c5 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -26,6 +26,9 @@ #include #include +#include +#include + #include #include #include @@ -66,9 +69,14 @@ namespace { std::vector gather_proposed_operations_digests(const graphene::chain::transaction& trx) { proposed_operations_digest_accumulator digest_accumulator; + for (auto& operation: trx.operations) { - operation.visit(digest_accumulator); + if( operation.which() != graphene::chain::operation::tag::value + && operation.which() != graphene::chain::operation::tag::value ) + operation.visit(digest_accumulator); + else + edump( ("Found dup")); } return digest_accumulator.proposed_operations_digests; @@ -148,10 +156,8 @@ void database::check_tansaction_for_duplicated_operations(const signed_transacti proposal_index.inspect_all_objects( [&](const object& obj){ const proposal_object& proposal = static_cast(obj); - for (auto& operation: proposal.proposed_transaction.operations) - { - existed_operations_digests.insert(fc::digest(operation)); - } + auto proposed_operations_digests = gather_proposed_operations_digests( proposal.proposed_transaction ); + existed_operations_digests.insert( proposed_operations_digests.begin(), proposed_operations_digests.end() ); }); for (auto& pending_transaction: _pending_tx) diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index eef57bac1..a7c259a88 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -35,6 +35,8 @@ #include #include +#include + #include #include #include @@ -2937,6 +2939,64 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test ) } FC_LOG_AND_RETHROW() } +// reworked check_transasction for duplicate +// now should not through an exception when there are different events with the same betting_market_group +// and or the same betting_market +BOOST_AUTO_TEST_CASE( check_transaction_for_duplicate_reworked_test ) +{ + std::vector names_vec(104); + + // create 104 pattern for first name + for( char co = 'A'; co <= 'D'; ++co ) { + for( char ci = 'A'; ci <= 'Z'; ++ci ) { + std::string first_name = std::to_string(co) + std::to_string(ci); + std::string second_name = first_name + first_name; + names_vec.push_back( {{ first_name, second_name }} ); + } + } + + sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id; + + event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id; + + betting_market_rules_id_type betting_market_rules_id = + create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id; + + for( const auto& name : names_vec ) + { + proposal_create_operation pcop = proposal_create_operation::committee_proposal( + db.get_global_properties().parameters, + db.head_block_time() + ); + pcop.review_period_seconds.reset(); + + event_create_operation evcop; + evcop.event_group_id = event_group_id; + evcop.name = name; + evcop.season = name; + + betting_market_group_create_operation bmgcop; + bmgcop.description = name; + bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0); + bmgcop.rules_id = betting_market_rules_id; + bmgcop.asset_id = asset_id_type(); + + betting_market_create_operation bmcop; + bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1); + bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) ); + + pcop.proposed_ops.emplace_back( evcop ); + pcop.proposed_ops.emplace_back( bmgcop ); + pcop.proposed_ops.emplace_back( bmcop ); + + signed_transaction trx; + set_expiration( db, trx ); + trx.operations.push_back( pcop ); + + process_operation_by_witnesses( pcop ); + } +} + BOOST_AUTO_TEST_SUITE_END() @@ -2951,7 +3011,7 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { std::cout << "Random number generator seeded to " << time(NULL) << std::endl; // betting operations don't take effect until HARDFORK 1000 - GRAPHENE_TESTING_GENESIS_TIMESTAMP = HARDFORK_1000_TIME.sec_since_epoch(); + GRAPHENE_TESTING_GENESIS_TIMESTAMP = HARDFORK_1000_TIME.sec_since_epoch() + 2; return nullptr; } diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index c6a216406..3da01662a 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -59,7 +59,7 @@ using namespace graphene::chain::test; -uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP = 1431700000; +uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP = 1431700002; namespace graphene { namespace chain { diff --git a/tests/tests/network_broadcast_api_tests.cpp b/tests/tests/network_broadcast_api_tests.cpp index 1c061fb3f..1405fc8c1 100644 --- a/tests/tests/network_broadcast_api_tests.cpp +++ b/tests/tests/network_broadcast_api_tests.cpp @@ -1,5 +1,9 @@ #include +#include +#include +#include +#include #include #include #include @@ -349,4 +353,63 @@ BOOST_AUTO_TEST_CASE( check_fails_for_several_transactions_with_duplicates_in_pe } } +BOOST_AUTO_TEST_CASE( check_passes_for_duplicated_betting_market_or_group ) +{ + generate_blocks( HARDFORK_1000_TIME + fc::seconds(300) ); + + try + { + const sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id; + const event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id; + const betting_market_rules_id_type betting_market_rules_id = + create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id; + + event_create_operation evcop1; + evcop1.event_group_id = event_group_id; + evcop1.name = {{"NO", "NAME_ONE"}}; + evcop1.season = {{"NO", "NAME_ONE"}}; + + event_create_operation evcop2; + evcop2.event_group_id = event_group_id; + evcop2.name = {{"NT", "NAME_TWO"}}; + evcop2.season = {{"NT", "NAME_TWO"}}; + + betting_market_group_create_operation bmgcop; + bmgcop.description = {{"NN", "NO_NAME"}}; + bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0); + bmgcop.rules_id = betting_market_rules_id; + bmgcop.asset_id = asset_id_type(); + + betting_market_create_operation bmcop; + bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1); + bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) ); + + proposal_create_operation pcop1 = proposal_create_operation::committee_proposal( + db.get_global_properties().parameters, + db.head_block_time() + ); + pcop1.review_period_seconds.reset(); + + proposal_create_operation pcop2 = pcop1; + + pcop1.proposed_ops.emplace_back( evcop1 ); + pcop1.proposed_ops.emplace_back( bmgcop ); + pcop1.proposed_ops.emplace_back( bmcop ); + + pcop2.proposed_ops.emplace_back( evcop2 ); + pcop2.proposed_ops.emplace_back( bmgcop ); + pcop2.proposed_ops.emplace_back( bmcop ); + + create_proposal(*this, { pcop1, pcop2 }); + + auto trx = make_signed_transaction_with_proposed_operation(*this, { pcop1, pcop2 }); + BOOST_CHECK_NO_THROW( db.check_tansaction_for_duplicated_operations(trx) ); + } + catch( const fc::exception& e ) + { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_SUITE_END()