moved check_trx_for_duplicate_operation and digest_accumulator to database api

This commit is contained in:
dimfred 2019-01-28 11:51:26 +01:00
parent fe138fabbf
commit ee8429938c
4 changed files with 75 additions and 63 deletions

View file

@ -45,6 +45,42 @@
typedef std::map< std::pair<graphene::chain::asset_id_type, graphene::chain::asset_id_type>, std::vector<fc::variant> > market_queue_type;
namespace {
struct proposed_operations_digest_accumulator
{
typedef void result_type;
void operator()(const graphene::chain::proposal_create_operation& proposal)
{
for (auto& operation: proposal.proposed_ops)
{
proposed_operations_digests.push_back(fc::digest(operation.op));
}
}
//empty template method is needed for all other operation types
//we can ignore them, we are interested in only proposal_create_operation
template<class T>
void operator()(const T&)
{}
std::vector<fc::sha256> proposed_operations_digests;
};
std::vector<fc::sha256> gather_proposed_operations_digests(const graphene::chain::transaction& trx)
{
proposed_operations_digest_accumulator digest_accumulator;
for (auto& operation: trx.operations)
{
operation.visit(digest_accumulator);
}
return digest_accumulator.proposed_operations_digests;
}
}
namespace graphene { namespace app {
class database_api_impl;
@ -70,6 +106,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
map<uint32_t, optional<block_header>> get_block_header_batch(const vector<uint32_t> block_nums)const;
optional<signed_block> get_block(uint32_t block_num)const;
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;
void check_transaction_for_duplicated_operations(const signed_transaction& trx);
// Globals
chain_property_object get_chain_properties()const;
@ -429,6 +466,37 @@ processed_transaction database_api_impl::get_transaction(uint32_t block_num, uin
return opt_block->transactions[trx_num];
}
void database_api::check_transaction_for_duplicated_operations(const signed_transaction& trx)
{
my->check_transaction_for_duplicated_operations(trx);
}
void database_api_impl::check_transaction_for_duplicated_operations(const signed_transaction& trx)
{
const auto& proposal_index = get_index<proposal_object>();
std::set<fc::sha256> existed_operations_digests;
proposal_index.inspect_all_objects( [&](const object& obj){
const proposal_object& proposal = static_cast<const proposal_object&>(obj);
for (auto& operation: proposal.proposed_transaction.operations)
{
existed_operations_digests.insert(fc::digest(operation));
}
});
for (auto& pending_transaction: _pending_tx)
{
auto proposed_operations_digests = gather_proposed_operations_digests(pending_transaction);
existed_operations_digests.insert(proposed_operations_digests.begin(), proposed_operations_digests.end());
}
auto proposed_operations_digests = gather_proposed_operations_digests(trx);
for (auto& digest: proposed_operations_digests)
{
FC_ASSERT(existed_operations_digests.count(digest) == 0, "Proposed operation is already pending for approval.");
}
}
//////////////////////////////////////////////////////////////////////
// //
// Globals //

View file

@ -192,6 +192,12 @@ class database_api
*/
optional<signed_transaction> get_recent_transaction_by_id( const transaction_id_type& id )const;
/**
* TODO
*
*/
void check_transaction_for_duplicated_operations(const signed_transaction& trx);
/////////////
// Globals //
/////////////
@ -645,6 +651,7 @@ class database_api
*/
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
private:
std::shared_ptr< database_api_impl > my;
};

View file

@ -40,41 +40,6 @@
#include <fc/smart_ref_impl.hpp>
namespace {
struct proposed_operations_digest_accumulator
{
typedef void result_type;
void operator()(const graphene::chain::proposal_create_operation& proposal)
{
for (auto& operation: proposal.proposed_ops)
{
proposed_operations_digests.push_back(fc::digest(operation.op));
}
}
//empty template method is needed for all other operation types
//we can ignore them, we are interested in only proposal_create_operation
template<class T>
void operator()(const T&)
{}
std::vector<fc::sha256> proposed_operations_digests;
};
std::vector<fc::sha256> gather_proposed_operations_digests(const graphene::chain::transaction& trx)
{
proposed_operations_digest_accumulator digest_accumulator;
for (auto& operation: trx.operations)
{
operation.visit(digest_accumulator);
}
return digest_accumulator.proposed_operations_digests;
}
}
namespace graphene { namespace chain {
bool database::is_known_block( const block_id_type& id )const
@ -140,32 +105,6 @@ std::vector<block_id_type> database::get_block_ids_on_fork(block_id_type head_of
result.emplace_back(branches.first.back()->previous_id());
return result;
}
void database::check_tansaction_for_duplicated_operations(const signed_transaction& trx)
{
const auto& proposal_index = get_index<proposal_object>();
std::set<fc::sha256> existed_operations_digests;
proposal_index.inspect_all_objects( [&](const object& obj){
const proposal_object& proposal = static_cast<const proposal_object&>(obj);
for (auto& operation: proposal.proposed_transaction.operations)
{
existed_operations_digests.insert(fc::digest(operation));
}
});
for (auto& pending_transaction: _pending_tx)
{
auto proposed_operations_digests = gather_proposed_operations_digests(pending_transaction);
existed_operations_digests.insert(proposed_operations_digests.begin(), proposed_operations_digests.end());
}
auto proposed_operations_digests = gather_proposed_operations_digests(trx);
for (auto& digest: proposed_operations_digests)
{
FC_ASSERT(existed_operations_digests.count(digest) == 0, "Proposed operation is already pending for approval.");
}
}
/**
* Push block "may fail" in which case every partial change is unwound. After

View file

@ -136,8 +136,6 @@ namespace graphene { namespace chain {
void add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts );
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
bool before_last_checkpoint()const;
void check_tansaction_for_duplicated_operations(const signed_transaction& trx);
bool push_block( const signed_block& b, uint32_t skip = skip_nothing );
processed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );