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;
|
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 {
|
namespace graphene { namespace app {
|
||||||
|
|
||||||
class database_api_impl;
|
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;
|
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;
|
optional<signed_block> get_block(uint32_t block_num)const;
|
||||||
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )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
|
// Globals
|
||||||
chain_property_object get_chain_properties()const;
|
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];
|
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 //
|
// Globals //
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,12 @@ class database_api
|
||||||
*/
|
*/
|
||||||
optional<signed_transaction> get_recent_transaction_by_id( const transaction_id_type& id )const;
|
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 //
|
// Globals //
|
||||||
/////////////
|
/////////////
|
||||||
|
|
@ -645,6 +651,7 @@ class database_api
|
||||||
*/
|
*/
|
||||||
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
|
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr< database_api_impl > my;
|
std::shared_ptr< database_api_impl > my;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -40,41 +40,6 @@
|
||||||
|
|
||||||
#include <fc/smart_ref_impl.hpp>
|
#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 {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
bool database::is_known_block( const block_id_type& id )const
|
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());
|
result.emplace_back(branches.first.back()->previous_id());
|
||||||
return result;
|
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
|
* 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 );
|
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; }
|
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
|
||||||
bool before_last_checkpoint()const;
|
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 );
|
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 );
|
processed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue