moved check_trx_for_duplicate_operation and digest_accumulator to database api
This commit is contained in:
parent
fe138fabbf
commit
ee8429938c
4 changed files with 75 additions and 63 deletions
|
|
@ -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 //
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
Loading…
Reference in a new issue