Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Account lookup by key #241

Merged
merged 3 commits into from
Aug 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libraries/chain/include/eos/chain/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ namespace eos { namespace chain {
chain_property_object_type,
account_transaction_history_object_type, ///< Defined by account_history_plugin
transaction_history_object_type, ///< Defined by account_history_plugin
public_key_history_object_type, ///< Defined by account_history_plugin
balance_object_type, ///< Defined by native_contract library
staked_balance_object_type, ///< Defined by native_contract library
producer_votes_object_type, ///< Defined by native_contract library
Expand Down Expand Up @@ -226,6 +227,7 @@ FC_REFLECT_ENUM(eos::chain::object_type,
(chain_property_object_type)
(account_transaction_history_object_type)
(transaction_history_object_type)
(public_key_history_object_type)
(balance_object_type)
(staked_balance_object_type)
(producer_votes_object_type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ void account_history_api_plugin::plugin_startup() {

app().get_plugin<http_plugin>().add_api({
CHAIN_RO_CALL(get_transaction),
CHAIN_RO_CALL(get_transactions)
CHAIN_RO_CALL(get_transactions),
CHAIN_RO_CALL(get_key_accounts)
});
}

Expand Down
102 changes: 93 additions & 9 deletions plugins/account_history_plugin/account_history_plugin.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <eos/account_history_plugin/account_history_plugin.hpp>
#include <eos/account_history_plugin/account_transaction_history_object.hpp>
#include <eos/account_history_plugin/public_key_history_object.hpp>
#include <eos/account_history_plugin/transaction_history_object.hpp>
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/config.hpp>
Expand Down Expand Up @@ -36,6 +37,7 @@ class account_history_plugin_impl {
public:
ProcessedTransaction get_transaction(const chain::transaction_id_type& transaction_id) const;
get_transactions_results get_transactions(const AccountName& account_name, const optional<uint32_t>& skip_seq, const optional<uint32_t>& num_seq) const;
vector<AccountName> get_key_accounts(const public_key_type& public_key) const;
void applied_block(const signed_block&);

chain_plugin* chain_plug;
Expand All @@ -55,12 +57,25 @@ class account_history_plugin_impl {

optional<block_id_type> find_block_id(const chainbase::database& db, const transaction_id_type& transaction_id) const;
ProcessedTransaction find_transaction(const chain::transaction_id_type& transaction_id, const signed_block& block) const;
ProcessedTransaction find_transaction(const chain::transaction_id_type& transaction_id, const block_id_type& block_id) const;
bool is_scope_relevant(const eos::types::Vector<AccountName>& scope);
get_transactions_results ordered_transactions(const block_transaction_id_map& block_transaction_ids, const fc::time_point& start_time, const uint32_t begin, const uint32_t end) const;
static void add(chainbase::database& db, const vector<types::KeyPermissionWeight>& keys, const AccountName& account_name, const PermissionName& permission);
static void remove(chainbase::database& db, const AccountName& account_name, const PermissionName& permission);
bool time_exceeded(const fc::time_point& start_time) const;
static const AccountName NEW_ACCOUNT;
static const AccountName UPDATE_AUTH;
static const AccountName DELETE_AUTH;
static const PermissionName OWNER;
static const PermissionName ACTIVE;
static const PermissionName RECOVERY;
};
const int64_t account_history_plugin_impl::DEFAULT_TRANSACTION_TIME_LIMIT = 3;
const AccountName account_history_plugin_impl::NEW_ACCOUNT = "newaccount";
const AccountName account_history_plugin_impl::UPDATE_AUTH = "updateauth";
const AccountName account_history_plugin_impl::DELETE_AUTH = "deleteauth";
const PermissionName account_history_plugin_impl::OWNER = "owner";
const PermissionName account_history_plugin_impl::ACTIVE = "active";
const PermissionName account_history_plugin_impl::RECOVERY = "recovery";

optional<block_id_type> account_history_plugin_impl::find_block_id(const chainbase::database& db, const transaction_id_type& transaction_id) const
{
Expand All @@ -85,13 +100,6 @@ ProcessedTransaction account_history_plugin_impl::find_transaction(const chain::
FC_THROW("Transaction with ID ${tid} was indexed as being in block ID ${bid}, but was not found in that block", ("tid", transaction_id)("bid", block.id()));
}

ProcessedTransaction account_history_plugin_impl::find_transaction(const chain::transaction_id_type& transaction_id, const chain::block_id_type& block_id) const
{
auto block = chain_plug->chain().fetch_block_by_id(block_id);
FC_ASSERT(block, "Transaction with ID ${tid} was indexed as being in block ID ${bid}, but no such block was found", ("tid", transaction_id)("bid", block_id));
return find_transaction(transaction_id, *block);
}

ProcessedTransaction account_history_plugin_impl::get_transaction(const chain::transaction_id_type& transaction_id) const
{
const auto& db = chain_plug->chain().get_database();
Expand All @@ -101,7 +109,9 @@ ProcessedTransaction account_history_plugin_impl::get_transaction(const chain::t
} );
if( block_id.valid() )
{
return find_transaction(transaction_id, *block_id);
auto block = chain_plug->chain().fetch_block_by_id(*block_id);
FC_ASSERT(block, "Transaction with ID ${tid} was indexed as being in block ID ${bid}, but no such block was found", ("tid", transaction_id)("bid", block_id));
return find_transaction(transaction_id, *block);
}

#warning TODO: lookup of recent transactions
Expand Down Expand Up @@ -227,13 +237,30 @@ bool account_history_plugin_impl::time_exceeded(const fc::time_point& start_time
return (fc::time_point::now() - start_time).count() > transactions_time_limit;
}

vector<AccountName> account_history_plugin_impl::get_key_accounts(const public_key_type& public_key) const
{
std::set<AccountName> accounts;
const auto& db = chain_plug->chain().get_database();
db.with_read_lock( [&]() {
const auto& pub_key_idx = db.get_index<public_key_history_multi_index, by_pub_key>();
auto range = pub_key_idx.equal_range( public_key );
for (auto obj = range.first; obj != range.second; ++obj)
{
accounts.insert(obj->account_name);
}
} );
return vector<AccountName>(accounts.begin(), accounts.end());
}

void account_history_plugin_impl::applied_block(const signed_block& block)
{
const auto block_id = block.id();
auto& db = chain_plug->chain().get_mutable_database();
const bool check_relevance = filter_on.size();
for (const auto& cycle : block.cycles)
{
for (const auto& thread : cycle)
{
for (const auto& trx : thread.user_input)
{
if (check_relevance && !is_scope_relevant(trx.scope))
Expand All @@ -251,7 +278,59 @@ void account_history_plugin_impl::applied_block(const signed_block& block)
account_transaction_history.transaction_id = trx.id();
});
}

for (const chain::Message& msg : trx.messages)
{
if (msg.code == config::EosContractName)
{
if (msg.type == NEW_ACCOUNT)
{
const auto create = msg.as<types::newaccount>();
auto count = create.owner.keys.size() + create.active.keys.size() + create.recovery.keys.size();
add(db, create.owner.keys, create.name, OWNER);
add(db, create.active.keys, create.name, ACTIVE);
add(db, create.recovery.keys, create.name, RECOVERY);
}
else if (msg.type == UPDATE_AUTH)
{
const auto update = msg.as<types::updateauth>();
remove(db, update.account, update.permission);
add(db, update.authority.keys, update.account, update.permission);
}
else if (msg.type == DELETE_AUTH)
{
const auto del = msg.as<types::deleteauth>();
remove(db, del.account, del.permission);
}
}
}
}
}
}
}

void account_history_plugin_impl::add(chainbase::database& db, const vector<types::KeyPermissionWeight>& keys, const AccountName& account_name, const PermissionName& permission)
{
for (auto pub_key_weight : keys )
{
db.create<public_key_history_object>([&](public_key_history_object& obj) {
obj.public_key = pub_key_weight.key;
obj.account_name = account_name;
obj.permission = permission;
});
}
}

void account_history_plugin_impl::remove(chainbase::database& db, const AccountName& account_name, const PermissionName& permission)
{
const auto& acct_perm_idx = db.get_index<public_key_history_multi_index, by_account_permission>();
auto& mutatable_acct_perm_idx = db.get_mutable_index<public_key_history_multi_index>();
auto range = acct_perm_idx.equal_range( boost::make_tuple( account_name, permission ) );

for (auto acct_perm = range.first; acct_perm != range.second; ++acct_perm)
{
mutatable_acct_perm_idx.remove(*acct_perm);
}
}

bool account_history_plugin_impl::is_scope_relevant(const eos::types::Vector<AccountName>& scope)
Expand Down Expand Up @@ -300,6 +379,7 @@ void account_history_plugin::plugin_startup()
my->chain_plug = app().find_plugin<chain_plugin>();
auto& db = my->chain_plug->chain().get_mutable_database();
db.add_index<account_transaction_history_multi_index>();
db.add_index<public_key_history_multi_index>();
db.add_index<transaction_history_multi_index>();

my->chain_plug->chain().applied_block.connect ([&impl = my](const signed_block& block) {
Expand All @@ -324,5 +404,9 @@ read_only::get_transactions_results read_only::get_transactions(const read_only:
return account_history->get_transactions(params.account_name, params.skip_seq, params.num_seq);
}

read_only::get_key_accounts_results read_only::get_key_accounts(const get_key_accounts_params& params) const
{
return { account_history->get_key_accounts(params.public_key) };
}
} // namespace account_history_apis
} // namespace eos
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class read_only {
chain::transaction_id_type transaction_id;
fc::variant transaction;
};

get_transaction_results get_transaction(const get_transaction_params& params) const;

struct get_transactions_params {
chain::AccountName account_name;
optional<uint32_t> skip_seq;
Expand All @@ -51,6 +51,14 @@ class read_only {
};

get_transactions_results get_transactions(const get_transactions_params& params) const;

struct get_key_accounts_params {
chain::public_key_type public_key;
};
struct get_key_accounts_results {
vector<chain::AccountName> account_names;
};
get_key_accounts_results get_key_accounts(const get_key_accounts_params& params) const;
};

class read_write {
Expand Down Expand Up @@ -89,3 +97,5 @@ FC_REFLECT(eos::account_history_apis::read_only::get_transaction_results, (trans
FC_REFLECT(eos::account_history_apis::read_only::get_transactions_params, (account_name)(skip_seq)(num_seq) )
FC_REFLECT(eos::account_history_apis::read_only::ordered_transaction_results, (seq_num)(transaction_id)(transaction) )
FC_REFLECT(eos::account_history_apis::read_only::get_transactions_results, (transactions)(time_limit_exceeded_error) )
FC_REFLECT(eos::account_history_apis::read_only::get_key_accounts_params, (public_key) )
FC_REFLECT(eos::account_history_apis::read_only::get_key_accounts_results, (account_names) )
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#pragma once

#include <chainbase/chainbase.hpp>
#include <fc/array.hpp>

namespace std {

template<>
struct hash<eos::chain::public_key_type>
{
size_t operator()( const eos::chain::public_key_type& key ) const
{
std::hash<fc::ecc::public_key_data> hash;
return hash(key.key_data);
}
};
}

namespace eos {
using chain::AccountName;
using chain::public_key_type;
using chain::PermissionName;
using namespace boost::multi_index;

class public_key_history_object : public chainbase::object<chain::public_key_history_object_type, public_key_history_object> {
OBJECT_CTOR(public_key_history_object)

id_type id;
public_key_type public_key;
AccountName account_name;
PermissionName permission;
};

struct by_id;
struct by_pub_key;
struct by_account_permission;
using public_key_history_multi_index = chainbase::shared_multi_index_container<
public_key_history_object,
indexed_by<
ordered_unique<tag<by_id>, BOOST_MULTI_INDEX_MEMBER(public_key_history_object, public_key_history_object::id_type, id)>,
hashed_non_unique<tag<by_pub_key>, BOOST_MULTI_INDEX_MEMBER(public_key_history_object, public_key_type, public_key), std::hash<public_key_type> >,
hashed_non_unique<tag<by_account_permission>,
composite_key< public_key_history_object,
member<public_key_history_object, AccountName, &public_key_history_object::account_name>,
member<public_key_history_object, PermissionName, &public_key_history_object::permission>
>,
composite_key_hash<
std::hash<AccountName>,
std::hash<PermissionName>
>
>
>
>;

typedef chainbase::generic_index<public_key_history_multi_index> public_key_history_index;

}

CHAINBASE_SET_INDEX_TYPE( eos::public_key_history_object, eos::public_key_history_multi_index )

FC_REFLECT( eos::public_key_history_object, (public_key)(account_name)(permission) )

19 changes: 19 additions & 0 deletions programs/eosc/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const string get_account_func = chain_func_base + "/get_account";
const string account_history_func_base = "/v1/account_history";
const string get_transaction_func = account_history_func_base + "/get_transaction";
const string get_transactions_func = account_history_func_base + "/get_transactions";
const string get_key_accounts_func = account_history_func_base + "/get_key_accounts";

inline std::vector<Name> sort_names( std::vector<Name>&& names ) {
std::sort( names.begin(), names.end() );
Expand Down Expand Up @@ -130,6 +131,15 @@ void create_account( const vector<string>& cmd_line ) {
transaction_helpers::emplace_message(trx, config::EosContractName, vector<types::AccountPermission>{{creator,"active"}}, "newaccount",
types::newaccount{creator, newaccount, owner_auth,
active_auth, recovery_auth, deposit});
if (creator == "inita")
{
fc::optional<fc::ecc::private_key> private_key = eos::utilities::wif_to_key("5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3");
if (private_key)
{
wlog("public key ${k}",("k", private_key->get_public_key()));
trx.sign(*private_key, eos::chain::chain_id_type{});
}
}

std::cout << fc::json::to_pretty_string( push_transaction(trx) ) << std::endl;

Expand Down Expand Up @@ -386,6 +396,15 @@ int send_command (const vector<string> &cmd_line)
? fc::mutable_variant_object( "account_name", account_name)("skip_seq", cmd_line[2])
: fc::mutable_variant_object( "account_name", account_name)("skip_seq", cmd_line[2])("num_seq", cmd_line[3]);
std::cout << fc::json::to_pretty_string( call( get_transactions_func, arg) ) << std::endl;
} else if( command == "accounts" ) {
if( cmd_line.size() != 2 )
{
std::cerr << "usage: " << program << " accounts PUBLIC_KEY\n";
return -1;
}
chain::public_key_type public_key(cmd_line[1]);
auto arg = fc::mutable_variant_object( "public_key", public_key);
std::cout << fc::json::to_pretty_string( call( get_key_accounts_func, arg) ) << std::endl;
}
return 0;
}
Expand Down