Added more tests. Fixed offsets in the db file. Pathced the network_broadcast_api.
This commit is contained in:
parent
1c74bba60d
commit
140ecd7532
3 changed files with 107 additions and 34 deletions
|
|
@ -163,12 +163,15 @@ namespace graphene { namespace app {
|
||||||
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
|
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
|
||||||
{
|
{
|
||||||
trx.validate();
|
trx.validate();
|
||||||
|
_app.chain_database()->check_tansaction_for_duplicated_operations(trx);
|
||||||
_app.chain_database()->push_transaction(trx);
|
_app.chain_database()->push_transaction(trx);
|
||||||
_app.p2p_node()->broadcast_transaction(trx);
|
_app.p2p_node()->broadcast_transaction(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx)
|
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx)
|
||||||
{
|
{
|
||||||
|
_app.chain_database()->check_tansaction_for_duplicated_operations(trx);
|
||||||
|
|
||||||
fc::promise<fc::variant>::ptr prom( new fc::promise<fc::variant>() );
|
fc::promise<fc::variant>::ptr prom( new fc::promise<fc::variant>() );
|
||||||
broadcast_transaction_with_callback( [=]( const fc::variant& v ){
|
broadcast_transaction_with_callback( [=]( const fc::variant& v ){
|
||||||
prom->set_value(v);
|
prom->set_value(v);
|
||||||
|
|
|
||||||
|
|
@ -130,27 +130,35 @@ std::vector<block_id_type> database::get_block_ids_on_fork(block_id_type head_of
|
||||||
|
|
||||||
void database::check_tansaction_for_duplicated_operations(const signed_transaction& trx)
|
void database::check_tansaction_for_duplicated_operations(const signed_transaction& trx)
|
||||||
{
|
{
|
||||||
const auto& proposal_index = this->get_index<proposal_object>();
|
const auto& proposal_index = get_index<proposal_object>();
|
||||||
std::set<fc::sha256> existed_operations_digests;
|
std::set<fc::sha256> existed_operations_digests;
|
||||||
|
|
||||||
proposal_index.inspect_all_objects( [&](const object& obj){
|
proposal_index.inspect_all_objects( [&](const object& obj){
|
||||||
const proposal_object& proposal = static_cast<const proposal_object&>(obj);
|
const proposal_object& proposal = static_cast<const proposal_object&>(obj);
|
||||||
for (auto& operation: proposal.proposed_transaction.operations)
|
for (auto& operation: proposal.proposed_transaction.operations)
|
||||||
{
|
{
|
||||||
existed_operations_digests.insert(fc::digest(operation));
|
existed_operations_digests.insert(fc::digest(operation));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
proposed_operations_digest_accumulator digest_accumulator;
|
for (auto& pending_transaction: _pending_tx)
|
||||||
for (auto& operation: trx.operations)
|
{
|
||||||
{
|
for (auto& operation: pending_transaction.operations)
|
||||||
operation.visit(digest_accumulator);
|
{
|
||||||
}
|
existed_operations_digests.insert(fc::digest(operation));
|
||||||
|
}
|
||||||
for (auto& digest: digest_accumulator.proposed_operations_digests)
|
}
|
||||||
{
|
|
||||||
FC_ASSERT(existed_operations_digests.count(digest) == 0, "Proposed operation is already pending for approval.");
|
proposed_operations_digest_accumulator digest_accumulator;
|
||||||
}
|
for (auto& operation: trx.operations)
|
||||||
|
{
|
||||||
|
operation.visit(digest_accumulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& digest: digest_accumulator.proposed_operations_digests)
|
||||||
|
{
|
||||||
|
FC_ASSERT(existed_operations_digests.count(digest) == 0, "Proposed operation is already pending for approval.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,12 @@ namespace
|
||||||
return transfer;
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void propose_operation(database_fixture& fixture, const operation& op)
|
void create_proposal(database_fixture& fixture, const std::vector<operation>& operations)
|
||||||
{
|
{
|
||||||
signed_transaction transaction;
|
signed_transaction transaction;
|
||||||
set_expiration(fixture.db, transaction);
|
set_expiration(fixture.db, transaction);
|
||||||
|
|
||||||
transaction.operations = {op};
|
transaction.operations = operations;
|
||||||
|
|
||||||
fixture.db.create<proposal_object>([&](proposal_object& proposal)
|
fixture.db.create<proposal_object>([&](proposal_object& proposal)
|
||||||
{
|
{
|
||||||
|
|
@ -59,20 +59,24 @@ namespace
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_transaction make_signed_transaction_with_proposed_operation(database_fixture& fixture, const operation& op)
|
signed_transaction make_signed_transaction_with_proposed_operation(database_fixture& fixture, const std::vector<operation>& operations)
|
||||||
{
|
{
|
||||||
proposal_create_operation operation_proposal;
|
proposal_create_operation operation_proposal;
|
||||||
operation_proposal.proposed_ops = {op_wrapper(op)};
|
|
||||||
|
for (auto& operation: operations)
|
||||||
|
{
|
||||||
|
operation_proposal.proposed_ops = {op_wrapper(operation)};
|
||||||
|
}
|
||||||
|
|
||||||
signed_transaction transaction;
|
signed_transaction transaction;
|
||||||
set_expiration( fixture.db, transaction );
|
set_expiration(fixture.db, transaction);
|
||||||
transaction.operations = {operation_proposal};
|
transaction.operations = {operation_proposal};
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE( check_transactions_duplicates_tests, database_fixture )
|
BOOST_FIXTURE_TEST_SUITE( check_tansaction_for_duplicated_operations, database_fixture )
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_twice )
|
BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_twice )
|
||||||
{
|
{
|
||||||
|
|
@ -80,9 +84,9 @@ BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_tw
|
||||||
{
|
{
|
||||||
ACTORS((alice))
|
ACTORS((alice))
|
||||||
|
|
||||||
::propose_operation(*this, make_transfer_operation(account_id_type(), alice_id, asset(500)));
|
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||||
|
|
||||||
auto trx = make_signed_transaction_with_proposed_operation(*this, make_transfer_operation(account_id_type(), alice_id, asset(500)));
|
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||||
}
|
}
|
||||||
catch( const fc::exception& e )
|
catch( const fc::exception& e )
|
||||||
|
|
@ -92,13 +96,13 @@ BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_tw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( test_check_passes_without_duplication )
|
BOOST_AUTO_TEST_CASE( check_passes_without_duplication )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ACTORS((alice))
|
ACTORS((alice))
|
||||||
|
|
||||||
auto trx = make_signed_transaction_with_proposed_operation(*this, make_transfer_operation(account_id_type(), alice_id, asset(500)));
|
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||||
}
|
}
|
||||||
catch( const fc::exception& e )
|
catch( const fc::exception& e )
|
||||||
|
|
@ -108,15 +112,15 @@ BOOST_AUTO_TEST_CASE( test_check_passes_without_duplication )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_with_different_assets )
|
BOOST_AUTO_TEST_CASE( check_passes_for_the_same_operation_with_different_assets )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ACTORS((alice))
|
ACTORS((alice))
|
||||||
|
|
||||||
::propose_operation(*this, make_transfer_operation(account_id_type(), alice_id, asset(500)));
|
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||||
|
|
||||||
auto trx = make_signed_transaction_with_proposed_operation(*this, make_transfer_operation(account_id_type(), alice_id, asset(501)));
|
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501))});
|
||||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||||
}
|
}
|
||||||
catch( const fc::exception& e )
|
catch( const fc::exception& e )
|
||||||
|
|
@ -126,4 +130,62 @@ BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_with_differ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( check_fails_for_duplication_in_transaction_with_several_operations )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ACTORS((alice))
|
||||||
|
|
||||||
|
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||||
|
|
||||||
|
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
|
||||||
|
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||||
|
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||||
|
}
|
||||||
|
catch( const fc::exception& e )
|
||||||
|
{
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_with_several_operations_and_transaction_with_several_operations )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ACTORS((alice))
|
||||||
|
|
||||||
|
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(499)),
|
||||||
|
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||||
|
|
||||||
|
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
|
||||||
|
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||||
|
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||||
|
}
|
||||||
|
catch( const fc::exception& e )
|
||||||
|
{
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_with_several_operations )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ACTORS((alice))
|
||||||
|
|
||||||
|
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(499)),
|
||||||
|
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||||
|
|
||||||
|
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||||
|
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||||
|
}
|
||||||
|
catch( const fc::exception& e )
|
||||||
|
{
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue