WIP, SON operations, cli_wallet commands and RPC
- create_son, update_son, delete_son, list_sons - get_sons, get_son_by_account, lookup_son_accounts, get_son_count
This commit is contained in:
parent
e2c579bb02
commit
3a65102e56
4 changed files with 292 additions and 10 deletions
|
|
@ -137,7 +137,10 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
map<string, committee_member_id_type> lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const;
|
||||
|
||||
// SON members
|
||||
fc::optional<son_object> get_son_member_by_account(account_id_type account)const;
|
||||
vector<optional<son_object>> get_sons(const vector<son_id_type>& son_ids)const;
|
||||
fc::optional<son_object> get_son_by_account(account_id_type account)const;
|
||||
map<string, son_id_type> lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const;
|
||||
uint64_t get_son_count()const;
|
||||
|
||||
// Votes
|
||||
vector<variant> lookup_vote_ids( const vector<vote_id_type>& votes )const;
|
||||
|
|
@ -1586,12 +1589,29 @@ map<string, committee_member_id_type> database_api_impl::lookup_committee_member
|
|||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
fc::optional<son_object> database_api::get_son_member_by_account(account_id_type account)const
|
||||
vector<optional<son_object>> database_api::get_sons(const vector<son_id_type>& son_ids)const
|
||||
{
|
||||
return my->get_son_member_by_account( account );
|
||||
return my->get_sons( son_ids );
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api_impl::get_son_member_by_account(account_id_type account) const
|
||||
vector<optional<son_object>> database_api_impl::get_sons(const vector<son_id_type>& son_ids)const
|
||||
{
|
||||
vector<optional<son_object>> result; result.reserve(son_ids.size());
|
||||
std::transform(son_ids.begin(), son_ids.end(), std::back_inserter(result),
|
||||
[this](son_id_type id) -> optional<son_object> {
|
||||
if(auto o = _db.find(id))
|
||||
return *o;
|
||||
return {};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api::get_son_by_account(account_id_type account)const
|
||||
{
|
||||
return my->get_son_by_account( account );
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type account) const
|
||||
{
|
||||
const auto& idx = _db.get_index_type<son_member_index>().indices().get<by_account>();
|
||||
auto itr = idx.find(account);
|
||||
|
|
@ -1600,6 +1620,44 @@ fc::optional<son_object> database_api_impl::get_son_member_by_account(account_id
|
|||
return {};
|
||||
}
|
||||
|
||||
map<string, son_id_type> database_api::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const
|
||||
{
|
||||
return my->lookup_son_accounts( lower_bound_name, limit );
|
||||
}
|
||||
|
||||
map<string, son_id_type> database_api_impl::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const
|
||||
{
|
||||
FC_ASSERT( limit <= 1000 );
|
||||
const auto& sons_by_id = _db.get_index_type<son_member_index>().indices().get<by_id>();
|
||||
|
||||
// we want to order sons by account name, but that name is in the account object
|
||||
// so the son_member_index doesn't have a quick way to access it.
|
||||
// get all the names and look them all up, sort them, then figure out what
|
||||
// records to return. This could be optimized, but we expect the
|
||||
// number of witnesses to be few and the frequency of calls to be rare
|
||||
std::map<std::string, son_id_type> sons_by_account_name;
|
||||
for (const son_object& son : sons_by_id)
|
||||
if (auto account_iter = _db.find(son.son_member_account))
|
||||
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
|
||||
sons_by_account_name.insert(std::make_pair(account_iter->name, son.id));
|
||||
|
||||
auto end_iter = sons_by_account_name.begin();
|
||||
while (end_iter != sons_by_account_name.end() && limit--)
|
||||
++end_iter;
|
||||
sons_by_account_name.erase(end_iter, sons_by_account_name.end());
|
||||
return sons_by_account_name;
|
||||
}
|
||||
|
||||
uint64_t database_api::get_son_count()const
|
||||
{
|
||||
return my->get_son_count();
|
||||
}
|
||||
|
||||
uint64_t database_api_impl::get_son_count()const
|
||||
{
|
||||
return _db.get_index_type<son_member_index>().indices().size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Votes //
|
||||
|
|
|
|||
|
|
@ -552,12 +552,33 @@ class database_api
|
|||
/////////////////
|
||||
|
||||
/**
|
||||
* @brief Get the son_member owned by a given account
|
||||
* @param account The ID of the account whose son_member should be retrieved
|
||||
* @return The son_member object, or null if the account does not have a son_member
|
||||
* @brief Get a list of SONs by ID
|
||||
* @param son_ids IDs of the SONs to retrieve
|
||||
* @return The SONs corresponding to the provided IDs
|
||||
*
|
||||
* This function has semantics identical to @ref get_objects
|
||||
*/
|
||||
fc::optional<son_object> get_son_member_by_account(account_id_type account)const;
|
||||
vector<optional<son_object>> get_sons(const vector<son_id_type>& son_ids)const;
|
||||
|
||||
/**
|
||||
* @brief Get the SON owned by a given account
|
||||
* @param account The ID of the account whose SON should be retrieved
|
||||
* @return The SON object, or null if the account does not have a SON
|
||||
*/
|
||||
fc::optional<son_object> get_son_by_account(account_id_type account)const;
|
||||
|
||||
/**
|
||||
* @brief Get names and IDs for registered SONs
|
||||
* @param lower_bound_name Lower bound of the first name to return
|
||||
* @param limit Maximum number of results to return -- must not exceed 1000
|
||||
* @return Map of SON names to corresponding IDs
|
||||
*/
|
||||
map<string, son_id_type> lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const;
|
||||
|
||||
/**
|
||||
* @brief Get the total number of SONs registered with the blockchain
|
||||
*/
|
||||
uint64_t get_son_count()const;
|
||||
|
||||
/// WORKERS
|
||||
|
||||
|
|
@ -770,7 +791,10 @@ FC_API(graphene::app::database_api,
|
|||
(lookup_committee_member_accounts)
|
||||
|
||||
// SON members
|
||||
(get_son_member_by_account)
|
||||
(get_sons)
|
||||
(get_son_by_account)
|
||||
(lookup_son_accounts)
|
||||
(get_son_count)
|
||||
|
||||
// workers
|
||||
(get_workers_by_account)
|
||||
|
|
|
|||
|
|
@ -1271,6 +1271,63 @@ class wallet_api
|
|||
*/
|
||||
committee_member_object get_committee_member(string owner_account);
|
||||
|
||||
|
||||
/** Creates a SON object owned by the given account.
|
||||
*
|
||||
* An account can have at most one SON object.
|
||||
*
|
||||
* @param owner_account the name or id of the account which is creating the SON
|
||||
* @param url a URL to include in the SON record in the blockchain. Clients may
|
||||
* display this when showing a list of SONs. May be blank.
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction registering a SON
|
||||
*/
|
||||
signed_transaction create_son(string owner_account,
|
||||
string url,
|
||||
bool broadcast = false);
|
||||
|
||||
/**
|
||||
* Update a SON object owned by the given account.
|
||||
*
|
||||
* @param witness The name of the SON's owner account. Also accepts the ID of the owner account or the ID of the SON.
|
||||
* @param url Same as for create_son. The empty string makes it remain the same.
|
||||
* @param block_signing_key The new block signing public key. The empty string makes it remain the same.
|
||||
* @param broadcast true if you wish to broadcast the transaction.
|
||||
*/
|
||||
signed_transaction update_son(string owner_account,
|
||||
string url,
|
||||
string block_signing_key,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
/** Deletes a SON object owned by the given account.
|
||||
*
|
||||
* An account can have at most one witness object.
|
||||
*
|
||||
* @param owner_account the name or id of the account which is creating the witness
|
||||
* @param url a URL to include in the witness record in the blockchain. Clients may
|
||||
* display this when showing a list of witnesses. May be blank.
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction registering a witness
|
||||
*/
|
||||
signed_transaction delete_son(string owner_account,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Lists all SONs in the blockchain.
|
||||
* This returns a list of all account names that own SON, and the associated SON id,
|
||||
* sorted by name. This lists SONs whether they are currently voted in or not.
|
||||
*
|
||||
* Use the \c lowerbound and limit parameters to page through the list. To retrieve all SONs,
|
||||
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
|
||||
* the last SON name returned as the \c lowerbound for the next \c list_sons() call.
|
||||
*
|
||||
* @param lowerbound the name of the first SON to return. If the named SON does not exist,
|
||||
* the list will start at the SON that comes after \c lowerbound
|
||||
* @param limit the maximum number of SON to return (max: 1000)
|
||||
* @returns a list of SON mapping SON names to SON ids
|
||||
*/
|
||||
map<string, son_id_type> list_sons(const string& lowerbound, uint32_t limit);
|
||||
|
||||
/** Creates a witness object owned by the given account.
|
||||
*
|
||||
* An account can have at most one witness object.
|
||||
|
|
@ -1980,6 +2037,10 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(get_committee_member)
|
||||
(list_witnesses)
|
||||
(list_committee_members)
|
||||
(create_son)
|
||||
(update_son)
|
||||
(delete_son)
|
||||
(list_sons)
|
||||
(create_witness)
|
||||
(update_witness)
|
||||
(create_worker)
|
||||
|
|
|
|||
|
|
@ -1720,6 +1720,41 @@ public:
|
|||
FC_CAPTURE_AND_RETHROW( (owner_account) )
|
||||
}
|
||||
|
||||
son_object get_son(string owner_account)
|
||||
{
|
||||
try
|
||||
{
|
||||
fc::optional<son_id_type> son_id = maybe_id<son_id_type>(owner_account);
|
||||
if (son_id)
|
||||
{
|
||||
std::vector<son_id_type> ids_to_get;
|
||||
ids_to_get.push_back(*son_id);
|
||||
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(ids_to_get);
|
||||
if (son_objects.front())
|
||||
return *son_objects.front();
|
||||
FC_THROW("No SON is registered for id ${id}", ("id", owner_account));
|
||||
}
|
||||
else
|
||||
{
|
||||
// then maybe it's the owner account
|
||||
try
|
||||
{
|
||||
account_id_type owner_account_id = get_account_id(owner_account);
|
||||
fc::optional<son_object> son = _remote_db->get_son_by_account(owner_account_id);
|
||||
if (son)
|
||||
return *son;
|
||||
else
|
||||
FC_THROW("No SON is registered for account ${account}", ("account", owner_account));
|
||||
}
|
||||
catch (const fc::exception&)
|
||||
{
|
||||
FC_THROW("No account or SON named ${account}", ("account", owner_account));
|
||||
}
|
||||
}
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW( (owner_account) )
|
||||
}
|
||||
|
||||
committee_member_object get_committee_member(string owner_account)
|
||||
{
|
||||
try
|
||||
|
|
@ -1755,6 +1790,84 @@ public:
|
|||
FC_CAPTURE_AND_RETHROW( (owner_account) )
|
||||
}
|
||||
|
||||
signed_transaction create_son(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
account_object son_account = get_account(owner_account);
|
||||
fc::ecc::private_key active_private_key = get_private_key_for_account(son_account);
|
||||
int son_key_index = find_first_unused_derived_key_index(active_private_key);
|
||||
fc::ecc::private_key son_private_key = derive_private_key(key_to_wif(active_private_key), son_key_index);
|
||||
graphene::chain::public_key_type son_public_key = son_private_key.get_public_key();
|
||||
|
||||
son_create_operation son_create_op;
|
||||
son_create_op.owner_account = son_account.id;
|
||||
son_create_op.signing_key = son_public_key;
|
||||
son_create_op.url = url;
|
||||
secret_hash_type::encoder enc;
|
||||
fc::raw::pack(enc, son_private_key);
|
||||
fc::raw::pack(enc, secret_hash_type());
|
||||
//son_create_op.initial_secret = secret_hash_type::hash(enc.result());
|
||||
|
||||
|
||||
if (_remote_db->get_son_by_account(son_create_op.owner_account))
|
||||
FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account));
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( son_create_op );
|
||||
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees);
|
||||
tx.validate();
|
||||
|
||||
//_wallet.pending_witness_registrations[owner_account] = key_to_wif(son_private_key);
|
||||
|
||||
return sign_transaction( tx, broadcast );
|
||||
} FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) }
|
||||
|
||||
signed_transaction update_son(string owner_account,
|
||||
string url,
|
||||
string block_signing_key,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
son_object son = get_son(owner_account);
|
||||
account_object son_account = get_account( son.son_member_account );
|
||||
fc::ecc::private_key active_private_key = get_private_key_for_account(son_account);
|
||||
|
||||
son_update_operation son_update_op;
|
||||
son_update_op.son_id = son.id;
|
||||
son_update_op.owner_account = son_account.id;
|
||||
if( url != "" )
|
||||
son_update_op.new_url = url;
|
||||
if( block_signing_key != "" ) {
|
||||
son_update_op.new_signing_key = public_key_type( block_signing_key );
|
||||
}
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( son_update_op );
|
||||
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees );
|
||||
tx.validate();
|
||||
|
||||
return sign_transaction( tx, broadcast );
|
||||
} FC_CAPTURE_AND_RETHROW( (owner_account)(url)(block_signing_key)(broadcast) ) }
|
||||
|
||||
signed_transaction delete_son(string owner_account,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
son_object son = get_son(owner_account);
|
||||
account_object son_account = get_account( son.son_member_account );
|
||||
fc::ecc::private_key active_private_key = get_private_key_for_account(son_account);
|
||||
|
||||
son_delete_operation son_delete_op;
|
||||
son_delete_op.son_id = son.id;
|
||||
son_delete_op.owner_account = son_account.id;
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( son_delete_op );
|
||||
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees );
|
||||
tx.validate();
|
||||
|
||||
return sign_transaction( tx, broadcast );
|
||||
} FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) }
|
||||
|
||||
signed_transaction create_witness(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
|
|
@ -2031,7 +2144,7 @@ public:
|
|||
{ try {
|
||||
account_object voting_account_object = get_account(voting_account);
|
||||
account_id_type son_member_owner_account_id = get_account_id(son_member);
|
||||
fc::optional<son_object> son_member_obj = _remote_db->get_son_member_by_account(son_member_owner_account_id);
|
||||
fc::optional<son_object> son_member_obj = _remote_db->get_son_by_account(son_member_owner_account_id);
|
||||
if (!son_member_obj)
|
||||
FC_THROW("Account ${son_member} is not registered as a son_member", ("son_member", son_member));
|
||||
if (approve)
|
||||
|
|
@ -4018,6 +4131,32 @@ committee_member_object wallet_api::get_committee_member(string owner_account)
|
|||
return my->get_committee_member(owner_account);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::create_son(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->create_son(owner_account, url, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::update_son(string owner_account,
|
||||
string url,
|
||||
string block_signing_key,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->update_son(owner_account, url, block_signing_key, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::delete_son(string owner_account,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
my->delete_son(owner_account, broadcast);
|
||||
}
|
||||
|
||||
map<string, son_id_type> wallet_api::list_sons(const string& lowerbound, uint32_t limit)
|
||||
{
|
||||
my->_remote_db->lookup_son_accounts(lowerbound, limit);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::create_witness(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
|
|
|
|||
Loading…
Reference in a new issue