Compare commits
13 commits
master
...
feature/rb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9f31f03d5 | ||
|
|
3f9965b213 | ||
|
|
f3cf062a42 | ||
|
|
c43ff2e53d | ||
|
|
4c2ea61c48 | ||
|
|
8ee292053a | ||
|
|
29e3802954 | ||
|
|
88a8753a60 | ||
|
|
4c2efdb871 | ||
|
|
b1124a166f | ||
|
|
f376503ac6 | ||
|
|
c74e83d088 | ||
|
|
2a7c8749d3 |
33 changed files with 2996 additions and 42 deletions
|
|
@ -31,25 +31,3 @@ test:
|
||||||
- ./tests/cli_test
|
- ./tests/cli_test
|
||||||
tags:
|
tags:
|
||||||
- builder
|
- builder
|
||||||
|
|
||||||
code_quality:
|
|
||||||
stage: test
|
|
||||||
image: docker:stable
|
|
||||||
variables:
|
|
||||||
DOCKER_DRIVER: overlay2
|
|
||||||
allow_failure: true
|
|
||||||
services:
|
|
||||||
- docker:stable-dind
|
|
||||||
script:
|
|
||||||
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
|
|
||||||
- docker run
|
|
||||||
--env SOURCE_CODE="$PWD"
|
|
||||||
--volume "$PWD":/code
|
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
|
|
||||||
artifacts:
|
|
||||||
paths: [gl-code-quality-report.json]
|
|
||||||
expire_in: 1 week
|
|
||||||
except:
|
|
||||||
variables:
|
|
||||||
- $CODE_QUALITY_DISABLED
|
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,14 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
||||||
// gpos
|
// gpos
|
||||||
gpos_info get_gpos_info(const account_id_type account) const;
|
gpos_info get_gpos_info(const account_id_type account) const;
|
||||||
|
|
||||||
|
// rbac
|
||||||
|
vector<custom_permission_object> get_custom_permissions(const account_id_type account) const;
|
||||||
|
fc::optional<custom_permission_object> get_custom_permission_by_name(const account_id_type account, const string& permission_name) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities(const account_id_type account) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_id(const custom_permission_id_type permission_id) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_name(const account_id_type account, const string& permission_name) const;
|
||||||
|
vector<authority> get_active_custom_account_authorities_by_operation(const account_id_type account, int operation_type) const;
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
const account_object* get_account_from_string( const std::string& name_or_id,
|
const account_object* get_account_from_string( const std::string& name_or_id,
|
||||||
bool throw_if_not_found = true ) const;
|
bool throw_if_not_found = true ) const;
|
||||||
|
|
@ -1857,6 +1865,9 @@ set<public_key_type> database_api_impl::get_required_signatures( const signed_tr
|
||||||
available_keys,
|
available_keys,
|
||||||
[&]( account_id_type id ){ return &id(_db).active; },
|
[&]( account_id_type id ){ return &id(_db).active; },
|
||||||
[&]( account_id_type id ){ return &id(_db).owner; },
|
[&]( account_id_type id ){ return &id(_db).owner; },
|
||||||
|
[&]( account_id_type id, const operation& op ) {
|
||||||
|
return _db.get_account_custom_authorities(id, op);
|
||||||
|
},
|
||||||
_db.get_global_properties().parameters.max_authority_depth );
|
_db.get_global_properties().parameters.max_authority_depth );
|
||||||
wdump((result));
|
wdump((result));
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1892,6 +1903,17 @@ set<public_key_type> database_api_impl::get_potential_signatures( const signed_t
|
||||||
result.insert(k);
|
result.insert(k);
|
||||||
return &auth;
|
return &auth;
|
||||||
},
|
},
|
||||||
|
[&]( account_id_type id, const operation& op ) {
|
||||||
|
vector<authority> custom_auths = _db.get_account_custom_authorities(id, op);
|
||||||
|
for (const auto& cauth: custom_auths)
|
||||||
|
{
|
||||||
|
for (const auto& k : cauth.get_keys())
|
||||||
|
{
|
||||||
|
result.insert(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return custom_auths;
|
||||||
|
},
|
||||||
_db.get_global_properties().parameters.max_authority_depth
|
_db.get_global_properties().parameters.max_authority_depth
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1919,6 +1941,9 @@ set<address> database_api_impl::get_potential_address_signatures( const signed_t
|
||||||
result.insert(k);
|
result.insert(k);
|
||||||
return &auth;
|
return &auth;
|
||||||
},
|
},
|
||||||
|
[&]( account_id_type id, const operation& op ) {
|
||||||
|
return _db.get_account_custom_authorities(id, op);
|
||||||
|
},
|
||||||
_db.get_global_properties().parameters.max_authority_depth
|
_db.get_global_properties().parameters.max_authority_depth
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1934,6 +1959,8 @@ bool database_api_impl::verify_authority( const signed_transaction& trx )const
|
||||||
trx.verify_authority( _db.get_chain_id(),
|
trx.verify_authority( _db.get_chain_id(),
|
||||||
[this]( account_id_type id ){ return &id(_db).active; },
|
[this]( account_id_type id ){ return &id(_db).active; },
|
||||||
[this]( account_id_type id ){ return &id(_db).owner; },
|
[this]( account_id_type id ){ return &id(_db).owner; },
|
||||||
|
[this]( account_id_type id, const operation& op ) {
|
||||||
|
return _db.get_account_custom_authorities(id, op); },
|
||||||
_db.get_global_properties().parameters.max_authority_depth );
|
_db.get_global_properties().parameters.max_authority_depth );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2303,6 +2330,118 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// RBAC methods //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
vector<custom_permission_object> database_api::get_custom_permissions(const account_id_type account) const
|
||||||
|
{
|
||||||
|
return my->get_custom_permissions(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_permission_object> database_api_impl::get_custom_permissions(const account_id_type account) const
|
||||||
|
{
|
||||||
|
const auto& pindex = _db.get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
|
||||||
|
auto prange = pindex.equal_range(boost::make_tuple(account));
|
||||||
|
vector<custom_permission_object> custom_permissions;
|
||||||
|
for(const custom_permission_object& pobj : boost::make_iterator_range(prange.first, prange.second))
|
||||||
|
{
|
||||||
|
custom_permissions.push_back(pobj);
|
||||||
|
}
|
||||||
|
return custom_permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::optional<custom_permission_object> database_api::get_custom_permission_by_name(const account_id_type account, const string& permission_name) const
|
||||||
|
{
|
||||||
|
return my->get_custom_permission_by_name(account, permission_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::optional<custom_permission_object> database_api_impl::get_custom_permission_by_name(const account_id_type account, const string& permission_name) const
|
||||||
|
{
|
||||||
|
const auto& pindex = _db.get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
|
||||||
|
auto prange = pindex.equal_range(boost::make_tuple(account, permission_name));
|
||||||
|
for(const custom_permission_object& pobj : boost::make_iterator_range(prange.first, prange.second))
|
||||||
|
{
|
||||||
|
return pobj;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> database_api::get_custom_account_authorities(const account_id_type account) const
|
||||||
|
{
|
||||||
|
return my->get_custom_account_authorities(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> database_api_impl::get_custom_account_authorities(const account_id_type account) const
|
||||||
|
{
|
||||||
|
const auto& pindex = _db.get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
|
||||||
|
const auto& cindex = _db.get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||||
|
vector<custom_account_authority_object> custom_account_auths;
|
||||||
|
auto prange = pindex.equal_range(boost::make_tuple(account));
|
||||||
|
for(const custom_permission_object& pobj : boost::make_iterator_range(prange.first, prange.second))
|
||||||
|
{
|
||||||
|
auto crange = cindex.equal_range(boost::make_tuple(pobj.id));
|
||||||
|
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||||
|
{
|
||||||
|
custom_account_auths.push_back(cobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return custom_account_auths;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> database_api::get_custom_account_authorities_by_permission_id(const custom_permission_id_type permission_id) const
|
||||||
|
{
|
||||||
|
return my->get_custom_account_authorities_by_permission_id(permission_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> database_api_impl::get_custom_account_authorities_by_permission_id(const custom_permission_id_type permission_id) const
|
||||||
|
{
|
||||||
|
const auto& cindex = _db.get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||||
|
vector<custom_account_authority_object> custom_account_auths;
|
||||||
|
auto crange = cindex.equal_range(boost::make_tuple(permission_id));
|
||||||
|
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||||
|
{
|
||||||
|
custom_account_auths.push_back(cobj);
|
||||||
|
}
|
||||||
|
return custom_account_auths;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> database_api::get_custom_account_authorities_by_permission_name(const account_id_type account, const string& permission_name) const
|
||||||
|
{
|
||||||
|
return my->get_custom_account_authorities_by_permission_name(account, permission_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> database_api_impl::get_custom_account_authorities_by_permission_name(const account_id_type account, const string& permission_name) const
|
||||||
|
{
|
||||||
|
vector<custom_account_authority_object> custom_account_auths;
|
||||||
|
fc::optional<custom_permission_object> pobj = get_custom_permission_by_name(account, permission_name);
|
||||||
|
if(!pobj)
|
||||||
|
{
|
||||||
|
return custom_account_auths;
|
||||||
|
}
|
||||||
|
const auto& cindex = _db.get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||||
|
auto crange = cindex.equal_range(boost::make_tuple(pobj->id));
|
||||||
|
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||||
|
{
|
||||||
|
custom_account_auths.push_back(cobj);
|
||||||
|
}
|
||||||
|
return custom_account_auths;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<authority> database_api::get_active_custom_account_authorities_by_operation(const account_id_type account, int operation_type) const
|
||||||
|
{
|
||||||
|
return my->get_active_custom_account_authorities_by_operation(account, operation_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<authority> database_api_impl::get_active_custom_account_authorities_by_operation(const account_id_type account, int operation_type) const
|
||||||
|
{
|
||||||
|
operation op;
|
||||||
|
op.set_which(operation_type);
|
||||||
|
return _db.get_account_custom_authorities(account, op);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// Private methods //
|
// Private methods //
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,9 @@
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
#include <graphene/chain/tournament_object.hpp>
|
#include <graphene/chain/tournament_object.hpp>
|
||||||
|
|
||||||
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
|
||||||
#include <graphene/market_history/market_history_plugin.hpp>
|
#include <graphene/market_history/market_history_plugin.hpp>
|
||||||
|
|
||||||
#include <fc/api.hpp>
|
#include <fc/api.hpp>
|
||||||
|
|
@ -709,6 +712,18 @@ class database_api
|
||||||
*/
|
*/
|
||||||
gpos_info get_gpos_info(const account_id_type account) const;
|
gpos_info get_gpos_info(const account_id_type account) const;
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// RBAC //
|
||||||
|
//////////
|
||||||
|
/**
|
||||||
|
* @return account and custom permissions/account-authorities info
|
||||||
|
*/
|
||||||
|
vector<custom_permission_object> get_custom_permissions(const account_id_type account) const;
|
||||||
|
fc::optional<custom_permission_object> get_custom_permission_by_name(const account_id_type account, const string& permission_name) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities(const account_id_type account) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_id(const custom_permission_id_type permission_id) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_name(const account_id_type account, const string& permission_name) const;
|
||||||
|
vector<authority> get_active_custom_account_authorities_by_operation(const account_id_type account, int operation_type) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -848,4 +863,12 @@ FC_API(graphene::app::database_api,
|
||||||
|
|
||||||
// gpos
|
// gpos
|
||||||
(get_gpos_info)
|
(get_gpos_info)
|
||||||
|
|
||||||
|
//rbac
|
||||||
|
(get_custom_permissions)
|
||||||
|
(get_custom_permission_by_name)
|
||||||
|
(get_custom_account_authorities)
|
||||||
|
(get_custom_account_authorities_by_permission_id)
|
||||||
|
(get_custom_account_authorities_by_permission_name)
|
||||||
|
(get_active_custom_account_authorities_by_operation)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ add_library( graphene_chain
|
||||||
protocol/vote.cpp
|
protocol/vote.cpp
|
||||||
protocol/tournament.cpp
|
protocol/tournament.cpp
|
||||||
protocol/small_ops.cpp
|
protocol/small_ops.cpp
|
||||||
|
protocol/custom_permission.cpp
|
||||||
|
protocol/custom_account_authority.cpp
|
||||||
|
|
||||||
genesis_state.cpp
|
genesis_state.cpp
|
||||||
get_config.cpp
|
get_config.cpp
|
||||||
|
|
@ -112,6 +114,8 @@ add_library( graphene_chain
|
||||||
betting_market_evaluator.cpp
|
betting_market_evaluator.cpp
|
||||||
betting_market_object.cpp
|
betting_market_object.cpp
|
||||||
betting_market_group_object.cpp
|
betting_market_group_object.cpp
|
||||||
|
custom_permission_evaluator.cpp
|
||||||
|
custom_account_authority_evaluator.cpp
|
||||||
|
|
||||||
affiliate_payout.cpp
|
affiliate_payout.cpp
|
||||||
|
|
||||||
|
|
|
||||||
147
libraries/chain/custom_account_authority_evaluator.cpp
Normal file
147
libraries/chain/custom_account_authority_evaluator.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include <graphene/chain/custom_account_authority_evaluator.hpp>
|
||||||
|
|
||||||
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
struct rbac_operation_hardfork_visitor
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
const fc::time_point_sec block_time;
|
||||||
|
|
||||||
|
rbac_operation_hardfork_visitor(const fc::time_point_sec bt) : block_time(bt) {}
|
||||||
|
void operator()(int op_type) const
|
||||||
|
{
|
||||||
|
int first_allowed_op = operation::tag<custom_permission_create_operation>::value;
|
||||||
|
switch (op_type)
|
||||||
|
{
|
||||||
|
case operation::tag<custom_permission_create_operation>::value:
|
||||||
|
case operation::tag<custom_permission_update_operation>::value:
|
||||||
|
case operation::tag<custom_permission_delete_operation>::value:
|
||||||
|
case operation::tag<custom_account_authority_create_operation>::value:
|
||||||
|
case operation::tag<custom_account_authority_update_operation>::value:
|
||||||
|
case operation::tag<custom_account_authority_delete_operation>::value:
|
||||||
|
FC_ASSERT(block_time >= HARDFORK_RBAC_TIME, "Custom permission not allowed on this operation yet!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FC_ASSERT(op_type < first_allowed_op, "Custom permission not allowed on this operation!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void_result create_custom_account_authority_evaluator::do_evaluate(const custom_account_authority_create_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const database &d = db();
|
||||||
|
auto now = d.head_block_time();
|
||||||
|
FC_ASSERT(now >= HARDFORK_RBAC_TIME, "Not allowed until RBAC HF");
|
||||||
|
op.owner_account(d);
|
||||||
|
const custom_permission_object &pobj = op.permission_id(d);
|
||||||
|
FC_ASSERT(pobj.account == op.owner_account, "Only owner account can update account authority object");
|
||||||
|
FC_ASSERT(op.valid_to > now, "valid_to expiry should be in future");
|
||||||
|
rbac_operation_hardfork_visitor rvtor(now);
|
||||||
|
rvtor(op.operation_type);
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_type create_custom_account_authority_evaluator::do_apply(const custom_account_authority_create_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database &d = db();
|
||||||
|
return d.create<custom_account_authority_object>([&op](custom_account_authority_object &obj) mutable {
|
||||||
|
obj.permission_id = op.permission_id;
|
||||||
|
obj.operation_type = op.operation_type;
|
||||||
|
obj.valid_from = op.valid_from;
|
||||||
|
obj.valid_to = op.valid_to;
|
||||||
|
})
|
||||||
|
.id;
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result update_custom_account_authority_evaluator::do_evaluate(const custom_account_authority_update_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const database &d = db();
|
||||||
|
auto now = d.head_block_time();
|
||||||
|
FC_ASSERT(now >= HARDFORK_RBAC_TIME, "Not allowed until RBAC HF");
|
||||||
|
op.owner_account(d);
|
||||||
|
const custom_account_authority_object &aobj = op.auth_id(d);
|
||||||
|
const custom_permission_object &pobj = aobj.permission_id(d);
|
||||||
|
FC_ASSERT(pobj.account == op.owner_account, "Only owner account can update account authority object");
|
||||||
|
auto valid_from = aobj.valid_from;
|
||||||
|
auto valid_to = aobj.valid_to;
|
||||||
|
if (op.new_valid_from)
|
||||||
|
{
|
||||||
|
valid_from = *op.new_valid_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op.new_valid_to)
|
||||||
|
{
|
||||||
|
FC_ASSERT(*op.new_valid_to > now, "New valid_to expiry should be in the future");
|
||||||
|
valid_to = *op.new_valid_to;
|
||||||
|
}
|
||||||
|
FC_ASSERT(valid_from < valid_to, "valid_from should be before valid_to");
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_type update_custom_account_authority_evaluator::do_apply(const custom_account_authority_update_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database &d = db();
|
||||||
|
const custom_account_authority_object &aobj = op.auth_id(d);
|
||||||
|
d.modify(aobj, [&op](custom_account_authority_object &obj) {
|
||||||
|
if (op.new_valid_from)
|
||||||
|
obj.valid_from = *op.new_valid_from;
|
||||||
|
if (op.new_valid_to)
|
||||||
|
obj.valid_to = *op.new_valid_to;
|
||||||
|
});
|
||||||
|
return op.auth_id;
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result delete_custom_account_authority_evaluator::do_evaluate(const custom_account_authority_delete_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const database &d = db();
|
||||||
|
auto now = d.head_block_time();
|
||||||
|
FC_ASSERT(now >= HARDFORK_RBAC_TIME, "Not allowed until RBAC HF");
|
||||||
|
op.owner_account(d);
|
||||||
|
const custom_account_authority_object &aobj = op.auth_id(d);
|
||||||
|
const custom_permission_object &pobj = aobj.permission_id(d);
|
||||||
|
FC_ASSERT(pobj.account == op.owner_account, "Only owner account can delete account authority object");
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result delete_custom_account_authority_evaluator::do_apply(const custom_account_authority_delete_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database &d = db();
|
||||||
|
const custom_account_authority_object &aobj = op.auth_id(d);
|
||||||
|
d.remove(aobj);
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
131
libraries/chain/custom_permission_evaluator.cpp
Normal file
131
libraries/chain/custom_permission_evaluator.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
#include <graphene/chain/custom_permission_evaluator.hpp>
|
||||||
|
|
||||||
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
void_result create_custom_permission_evaluator::do_evaluate(const custom_permission_create_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const database &d = db();
|
||||||
|
auto now = d.head_block_time();
|
||||||
|
FC_ASSERT(now >= HARDFORK_RBAC_TIME, "Not allowed until RBAC HF");
|
||||||
|
op.owner_account(d);
|
||||||
|
for (const auto &account_weight_pair : op.auth.account_auths)
|
||||||
|
{
|
||||||
|
account_weight_pair.first(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &pindex = d.get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
|
||||||
|
auto pitr = pindex.find(boost::make_tuple(op.owner_account, op.permission_name));
|
||||||
|
FC_ASSERT(pitr == pindex.end(), "Permission name already exists for the given account");
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_type create_custom_permission_evaluator::do_apply(const custom_permission_create_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database &d = db();
|
||||||
|
return d.create<custom_permission_object>([&op](custom_permission_object &obj) mutable {
|
||||||
|
obj.account = op.owner_account;
|
||||||
|
obj.permission_name = op.permission_name;
|
||||||
|
obj.auth = op.auth;
|
||||||
|
})
|
||||||
|
.id;
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result update_custom_permission_evaluator::do_evaluate(const custom_permission_update_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const database &d = db();
|
||||||
|
auto now = d.head_block_time();
|
||||||
|
FC_ASSERT(now >= HARDFORK_RBAC_TIME, "Not allowed until RBAC HF");
|
||||||
|
op.owner_account(d);
|
||||||
|
const custom_permission_object &pobj = op.permission_id(d);
|
||||||
|
FC_ASSERT(pobj.account == op.owner_account, "Only owner account can update permission object");
|
||||||
|
if (op.new_auth)
|
||||||
|
{
|
||||||
|
FC_ASSERT(!(*op.new_auth == pobj.auth), "New authority provided is not different from old authority");
|
||||||
|
for (const auto &account_weight_pair : op.new_auth->account_auths)
|
||||||
|
{
|
||||||
|
account_weight_pair.first(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_type update_custom_permission_evaluator::do_apply(const custom_permission_update_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database &d = db();
|
||||||
|
const custom_permission_object &pobj = op.permission_id(d);
|
||||||
|
d.modify(pobj, [&op](custom_permission_object &obj) {
|
||||||
|
if (op.new_auth)
|
||||||
|
obj.auth = *op.new_auth;
|
||||||
|
});
|
||||||
|
|
||||||
|
return op.permission_id;
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result delete_custom_permission_evaluator::do_evaluate(const custom_permission_delete_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const database &d = db();
|
||||||
|
auto now = d.head_block_time();
|
||||||
|
FC_ASSERT(now >= HARDFORK_RBAC_TIME, "Not allowed until RBAC HF");
|
||||||
|
op.owner_account(d);
|
||||||
|
const custom_permission_object &pobj = op.permission_id(d);
|
||||||
|
FC_ASSERT(pobj.account == op.owner_account, "Only owner account can delete permission object");
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result delete_custom_permission_evaluator::do_apply(const custom_permission_delete_operation &op)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database &d = db();
|
||||||
|
const custom_permission_object &pobj = op.permission_id(d);
|
||||||
|
// Remove the account authority objects linked to this permission
|
||||||
|
const auto& cindex = d.get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||||
|
vector<std::reference_wrapper<const custom_account_authority_object>> custom_auths;
|
||||||
|
auto crange = cindex.equal_range(boost::make_tuple(pobj.id));
|
||||||
|
// Store the references to the account authorities
|
||||||
|
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||||
|
{
|
||||||
|
custom_auths.push_back(cobj);
|
||||||
|
}
|
||||||
|
// Now remove the account authorities
|
||||||
|
for(const auto& cauth : custom_auths)
|
||||||
|
{
|
||||||
|
d.remove(cauth);
|
||||||
|
}
|
||||||
|
// Now finally remove the permission
|
||||||
|
d.remove(pobj);
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((op))
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
|
|
@ -790,7 +790,10 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
|
||||||
{
|
{
|
||||||
auto get_active = [&]( account_id_type id ) { return &id(*this).active; };
|
auto get_active = [&]( account_id_type id ) { return &id(*this).active; };
|
||||||
auto get_owner = [&]( account_id_type id ) { return &id(*this).owner; };
|
auto get_owner = [&]( account_id_type id ) { return &id(*this).owner; };
|
||||||
trx.verify_authority( chain_id, get_active, get_owner, get_global_properties().parameters.max_authority_depth );
|
auto get_custom = [&]( account_id_type id, const operation& op ) {
|
||||||
|
return get_account_custom_authorities(id, op);
|
||||||
|
};
|
||||||
|
trx.verify_authority( chain_id, get_active, get_owner, get_custom, get_global_properties().parameters.max_authority_depth );
|
||||||
}
|
}
|
||||||
|
|
||||||
//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
|
//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@
|
||||||
#include <graphene/chain/asset_object.hpp>
|
#include <graphene/chain/asset_object.hpp>
|
||||||
#include <graphene/chain/chain_property_object.hpp>
|
#include <graphene/chain/chain_property_object.hpp>
|
||||||
#include <graphene/chain/global_property_object.hpp>
|
#include <graphene/chain/global_property_object.hpp>
|
||||||
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
|
||||||
#include <fc/smart_ref_impl.hpp>
|
#include <fc/smart_ref_impl.hpp>
|
||||||
|
|
||||||
|
|
@ -159,4 +161,24 @@ const witness_schedule_object& database::get_witness_schedule_object()const
|
||||||
return *_p_witness_schedule_obj;
|
return *_p_witness_schedule_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<authority> database::get_account_custom_authorities(account_id_type account, const operation& op)const
|
||||||
|
{
|
||||||
|
const auto& pindex = get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
|
||||||
|
const auto& cindex = get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||||
|
auto prange = pindex.equal_range(boost::make_tuple(account));
|
||||||
|
time_point_sec now = head_block_time();
|
||||||
|
vector<authority> custom_auths;
|
||||||
|
for(const custom_permission_object& pobj : boost::make_iterator_range(prange.first, prange.second))
|
||||||
|
{
|
||||||
|
auto crange = cindex.equal_range(boost::make_tuple(pobj.id, op.which()));
|
||||||
|
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||||
|
{
|
||||||
|
if(now >= cobj.valid_from && now < cobj.valid_to)
|
||||||
|
{
|
||||||
|
custom_auths.push_back(pobj.auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return custom_auths;
|
||||||
|
}
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@
|
||||||
#include <graphene/chain/tournament_object.hpp>
|
#include <graphene/chain/tournament_object.hpp>
|
||||||
#include <graphene/chain/match_object.hpp>
|
#include <graphene/chain/match_object.hpp>
|
||||||
#include <graphene/chain/game_object.hpp>
|
#include <graphene/chain/game_object.hpp>
|
||||||
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <graphene/chain/sport_object.hpp>
|
#include <graphene/chain/sport_object.hpp>
|
||||||
|
|
@ -77,6 +79,8 @@
|
||||||
#include <graphene/chain/event_evaluator.hpp>
|
#include <graphene/chain/event_evaluator.hpp>
|
||||||
#include <graphene/chain/betting_market_evaluator.hpp>
|
#include <graphene/chain/betting_market_evaluator.hpp>
|
||||||
#include <graphene/chain/tournament_evaluator.hpp>
|
#include <graphene/chain/tournament_evaluator.hpp>
|
||||||
|
#include <graphene/chain/custom_permission_evaluator.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_evaluator.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||||
|
|
||||||
|
|
@ -243,6 +247,12 @@ void database::initialize_evaluators()
|
||||||
register_evaluator<lottery_reward_evaluator>();
|
register_evaluator<lottery_reward_evaluator>();
|
||||||
register_evaluator<lottery_end_evaluator>();
|
register_evaluator<lottery_end_evaluator>();
|
||||||
register_evaluator<sweeps_vesting_claim_evaluator>();
|
register_evaluator<sweeps_vesting_claim_evaluator>();
|
||||||
|
register_evaluator<create_custom_permission_evaluator>();
|
||||||
|
register_evaluator<update_custom_permission_evaluator>();
|
||||||
|
register_evaluator<delete_custom_permission_evaluator>();
|
||||||
|
register_evaluator<create_custom_account_authority_evaluator>();
|
||||||
|
register_evaluator<update_custom_account_authority_evaluator>();
|
||||||
|
register_evaluator<delete_custom_account_authority_evaluator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void database::initialize_indexes()
|
void database::initialize_indexes()
|
||||||
|
|
@ -284,6 +294,8 @@ void database::initialize_indexes()
|
||||||
tournament_details_idx->add_secondary_index<tournament_players_index>();
|
tournament_details_idx->add_secondary_index<tournament_players_index>();
|
||||||
add_index< primary_index<match_index> >();
|
add_index< primary_index<match_index> >();
|
||||||
add_index< primary_index<game_index> >();
|
add_index< primary_index<game_index> >();
|
||||||
|
add_index< primary_index<custom_permission_index> >();
|
||||||
|
add_index< primary_index<custom_account_authority_index> >();
|
||||||
|
|
||||||
//Implementation object indexes
|
//Implementation object indexes
|
||||||
add_index< primary_index<transaction_index > >();
|
add_index< primary_index<transaction_index > >();
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
#include <graphene/chain/witness_schedule_object.hpp>
|
#include <graphene/chain/witness_schedule_object.hpp>
|
||||||
#include <graphene/chain/worker_object.hpp>
|
#include <graphene/chain/worker_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
|
||||||
#define USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX // vesting_balance_object by_asset_balance index needed
|
#define USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX // vesting_balance_object by_asset_balance index needed
|
||||||
|
|
||||||
|
|
@ -933,6 +934,15 @@ void rolling_period_start(database& db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear_expired_custom_account_authorities(database& db)
|
||||||
|
{
|
||||||
|
const auto& cindex = db.get_index_type<custom_account_authority_index>().indices().get<by_expiration>();
|
||||||
|
while(!cindex.empty() && cindex.begin()->valid_to < db.head_block_time())
|
||||||
|
{
|
||||||
|
db.remove(*cindex.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Schedules payouts from a dividend distribution account to the current holders of the
|
// Schedules payouts from a dividend distribution account to the current holders of the
|
||||||
// dividend-paying asset. This takes any deposits made to the dividend distribution account
|
// dividend-paying asset. This takes any deposits made to the dividend distribution account
|
||||||
// since the last time it was called, and distributes them to the current owners of the
|
// since the last time it was called, and distributes them to the current owners of the
|
||||||
|
|
@ -1707,7 +1717,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
||||||
//for( const asset_bitasset_data_object* d : get_index_type<asset_bitasset_data_index>() )
|
//for( const asset_bitasset_data_object* d : get_index_type<asset_bitasset_data_index>() )
|
||||||
for( const auto& d : get_index_type<asset_bitasset_data_index>().indices() )
|
for( const auto& d : get_index_type<asset_bitasset_data_index>().indices() )
|
||||||
modify( d, [](asset_bitasset_data_object& o) { o.force_settled_volume = 0; });
|
modify( d, [](asset_bitasset_data_object& o) { o.force_settled_volume = 0; });
|
||||||
|
// Ideally we have to do this after every block but that leads to longer block applicaiton/replay times.
|
||||||
|
// So keep it here as it is not critical. valid_to check ensures
|
||||||
|
// these custom account auths are not usable.
|
||||||
|
clear_expired_custom_account_authorities(*this);
|
||||||
// process_budget needs to run at the bottom because
|
// process_budget needs to run at the bottom because
|
||||||
// it needs to know the next_maintenance_time
|
// it needs to know the next_maintenance_time
|
||||||
process_budget();
|
process_budget();
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,25 @@ struct get_impacted_account_visitor
|
||||||
void operator()( const sweeps_vesting_claim_operation& op ) {
|
void operator()( const sweeps_vesting_claim_operation& op ) {
|
||||||
_impacted.insert( op.account );
|
_impacted.insert( op.account );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()( const custom_permission_create_operation& op ){
|
||||||
|
_impacted.insert( op.owner_account );
|
||||||
|
}
|
||||||
|
void operator()( const custom_permission_update_operation& op ){
|
||||||
|
_impacted.insert( op.owner_account );
|
||||||
|
}
|
||||||
|
void operator()( const custom_permission_delete_operation& op ){
|
||||||
|
_impacted.insert( op.owner_account );
|
||||||
|
}
|
||||||
|
void operator()( const custom_account_authority_create_operation& op ){
|
||||||
|
_impacted.insert( op.owner_account );
|
||||||
|
}
|
||||||
|
void operator()( const custom_account_authority_update_operation& op ){
|
||||||
|
_impacted.insert( op.owner_account );
|
||||||
|
}
|
||||||
|
void operator()( const custom_account_authority_delete_operation& op ){
|
||||||
|
_impacted.insert( op.owner_account );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||||
|
|
|
||||||
4
libraries/chain/hardfork.d/RBAC.hf
Normal file
4
libraries/chain/hardfork.d/RBAC.hf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
// RBAC HARDFORK Wednesday, 20-May-20 00:00:00 UTC
|
||||||
|
#ifndef HARDFORK_RBAC_TIME
|
||||||
|
#define HARDFORK_RBAC_TIME (fc::time_point_sec( 1589932800 ))
|
||||||
|
#endif
|
||||||
|
|
@ -234,3 +234,6 @@
|
||||||
#define GPOS_PERIOD (60*60*24*30*6) // 6 months
|
#define GPOS_PERIOD (60*60*24*30*6) // 6 months
|
||||||
#define GPOS_SUBPERIOD (60*60*24*30) // 1 month
|
#define GPOS_SUBPERIOD (60*60*24*30) // 1 month
|
||||||
#define GPOS_VESTING_LOCKIN_PERIOD (60*60*24*30) // 1 month
|
#define GPOS_VESTING_LOCKIN_PERIOD (60*60*24*30) // 1 month
|
||||||
|
|
||||||
|
#define RBAC_MIN_PERMISSION_NAME_LENGTH 3
|
||||||
|
#define RBAC_MAX_PERMISSION_NAME_LENGTH 10
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/evaluator.hpp>
|
||||||
|
#include <graphene/chain/protocol/custom_account_authority.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
class create_custom_account_authority_evaluator : public evaluator<create_custom_account_authority_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef custom_account_authority_create_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate(const custom_account_authority_create_operation &o);
|
||||||
|
object_id_type do_apply(const custom_account_authority_create_operation &o);
|
||||||
|
};
|
||||||
|
|
||||||
|
class update_custom_account_authority_evaluator : public evaluator<update_custom_account_authority_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef custom_account_authority_update_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate(const custom_account_authority_update_operation &o);
|
||||||
|
object_id_type do_apply(const custom_account_authority_update_operation &o);
|
||||||
|
};
|
||||||
|
|
||||||
|
class delete_custom_account_authority_evaluator : public evaluator<delete_custom_account_authority_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef custom_account_authority_delete_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate(const custom_account_authority_delete_operation &o);
|
||||||
|
void_result do_apply(const custom_account_authority_delete_operation &o);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/db/object.hpp>
|
||||||
|
#include <graphene/db/generic_index.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
using namespace graphene::db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class custom_account_authority_object
|
||||||
|
* @brief Tracks the mappings between permission and operation types.
|
||||||
|
* @ingroup object
|
||||||
|
*/
|
||||||
|
class custom_account_authority_object : public abstract_object<custom_account_authority_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = custom_account_authority_object_type;
|
||||||
|
|
||||||
|
custom_permission_id_type permission_id;
|
||||||
|
int operation_type;
|
||||||
|
time_point_sec valid_from;
|
||||||
|
time_point_sec valid_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_id;
|
||||||
|
struct by_permission_and_op;
|
||||||
|
struct by_expiration;
|
||||||
|
using custom_account_authority_multi_index_type = multi_index_container<
|
||||||
|
custom_account_authority_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique< tag<by_id>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>,
|
||||||
|
ordered_unique< tag<by_permission_and_op>,
|
||||||
|
composite_key<custom_account_authority_object,
|
||||||
|
member<custom_account_authority_object, custom_permission_id_type, &custom_account_authority_object::permission_id>,
|
||||||
|
member<custom_account_authority_object, int, &custom_account_authority_object::operation_type>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
ordered_unique<tag<by_expiration>,
|
||||||
|
composite_key<custom_account_authority_object,
|
||||||
|
member<custom_account_authority_object, time_point_sec, &custom_account_authority_object::valid_to>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
using custom_account_authority_index = generic_index<custom_account_authority_object, custom_account_authority_multi_index_type>;
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::custom_account_authority_object, (graphene::db::object),
|
||||||
|
(permission_id)(operation_type)(valid_from)(valid_to) )
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/evaluator.hpp>
|
||||||
|
#include <graphene/chain/protocol/custom_permission.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
class create_custom_permission_evaluator : public evaluator<create_custom_permission_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef custom_permission_create_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate(const custom_permission_create_operation &o);
|
||||||
|
object_id_type do_apply(const custom_permission_create_operation &o);
|
||||||
|
};
|
||||||
|
|
||||||
|
class update_custom_permission_evaluator : public evaluator<update_custom_permission_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef custom_permission_update_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate(const custom_permission_update_operation &o);
|
||||||
|
object_id_type do_apply(const custom_permission_update_operation &o);
|
||||||
|
};
|
||||||
|
|
||||||
|
class delete_custom_permission_evaluator : public evaluator<delete_custom_permission_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef custom_permission_delete_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate(const custom_permission_delete_operation &o);
|
||||||
|
void_result do_apply(const custom_permission_delete_operation &o);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/db/object.hpp>
|
||||||
|
#include <graphene/db/generic_index.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
using namespace graphene::db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class custom_permission_object
|
||||||
|
* @brief Tracks all the custom permission of an account.
|
||||||
|
* @ingroup object
|
||||||
|
*/
|
||||||
|
class custom_permission_object : public abstract_object<custom_permission_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = custom_permission_object_type;
|
||||||
|
|
||||||
|
// Account for which this permission is being created
|
||||||
|
account_id_type account;
|
||||||
|
// Permission name
|
||||||
|
string permission_name;
|
||||||
|
// Authority required for this permission
|
||||||
|
authority auth;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_id;
|
||||||
|
struct by_account_and_permission;
|
||||||
|
using custom_permission_multi_index_type = multi_index_container<
|
||||||
|
custom_permission_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique< tag<by_id>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>,
|
||||||
|
ordered_unique< tag<by_account_and_permission>,
|
||||||
|
composite_key<custom_permission_object,
|
||||||
|
member<custom_permission_object, account_id_type, &custom_permission_object::account>,
|
||||||
|
member<custom_permission_object, string, &custom_permission_object::permission_name>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
using custom_permission_index = generic_index<custom_permission_object, custom_permission_multi_index_type>;
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::custom_permission_object, (graphene::db::object),
|
||||||
|
(account)(permission_name)(auth) )
|
||||||
|
|
@ -294,6 +294,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
||||||
uint32_t last_non_undoable_block_num() const;
|
uint32_t last_non_undoable_block_num() const;
|
||||||
|
vector<authority> get_account_custom_authorities(account_id_type account, const operation& op)const;
|
||||||
//////////////////// db_init.cpp ////////////////////
|
//////////////////// db_init.cpp ////////////////////
|
||||||
|
|
||||||
void initialize_evaluators();
|
void initialize_evaluators();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/base.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
struct custom_account_authority_create_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type
|
||||||
|
{
|
||||||
|
uint64_t fee = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
custom_permission_id_type permission_id;
|
||||||
|
int operation_type;
|
||||||
|
time_point_sec valid_from;
|
||||||
|
time_point_sec valid_to;
|
||||||
|
account_id_type owner_account;
|
||||||
|
|
||||||
|
account_id_type fee_payer() const { return owner_account; }
|
||||||
|
void validate() const;
|
||||||
|
share_type calculate_fee(const fee_parameters_type &k) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct custom_account_authority_update_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type
|
||||||
|
{
|
||||||
|
uint64_t fee = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
custom_account_authority_id_type auth_id;
|
||||||
|
optional<time_point_sec> new_valid_from;
|
||||||
|
optional<time_point_sec> new_valid_to;
|
||||||
|
account_id_type owner_account;
|
||||||
|
|
||||||
|
account_id_type fee_payer() const { return owner_account; }
|
||||||
|
void validate() const;
|
||||||
|
share_type calculate_fee(const fee_parameters_type &k) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct custom_account_authority_delete_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type
|
||||||
|
{
|
||||||
|
uint64_t fee = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
custom_account_authority_id_type auth_id;
|
||||||
|
account_id_type owner_account;
|
||||||
|
|
||||||
|
account_id_type fee_payer() const { return owner_account; }
|
||||||
|
void validate() const;
|
||||||
|
share_type calculate_fee(const fee_parameters_type &k) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::custom_account_authority_create_operation::fee_parameters_type, (fee))
|
||||||
|
FC_REFLECT(graphene::chain::custom_account_authority_create_operation, (fee)(permission_id)(operation_type)(valid_from)(valid_to)(owner_account))
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::custom_account_authority_update_operation::fee_parameters_type, (fee))
|
||||||
|
FC_REFLECT(graphene::chain::custom_account_authority_update_operation, (fee)(auth_id)(new_valid_from)(new_valid_to)(owner_account))
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::custom_account_authority_delete_operation::fee_parameters_type, (fee))
|
||||||
|
FC_REFLECT(graphene::chain::custom_account_authority_delete_operation, (fee)(auth_id)(owner_account))
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/base.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
struct custom_permission_create_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type
|
||||||
|
{
|
||||||
|
uint64_t fee = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
account_id_type owner_account;
|
||||||
|
string permission_name;
|
||||||
|
authority auth;
|
||||||
|
|
||||||
|
account_id_type fee_payer() const { return owner_account; }
|
||||||
|
void validate() const;
|
||||||
|
share_type calculate_fee(const fee_parameters_type &k) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct custom_permission_update_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type
|
||||||
|
{
|
||||||
|
uint64_t fee = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
custom_permission_id_type permission_id;
|
||||||
|
optional<authority> new_auth;
|
||||||
|
account_id_type owner_account;
|
||||||
|
|
||||||
|
account_id_type fee_payer() const { return owner_account; }
|
||||||
|
void validate() const;
|
||||||
|
share_type calculate_fee(const fee_parameters_type &k) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct custom_permission_delete_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type
|
||||||
|
{
|
||||||
|
uint64_t fee = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
custom_permission_id_type permission_id;
|
||||||
|
account_id_type owner_account;
|
||||||
|
|
||||||
|
account_id_type fee_payer() const { return owner_account; }
|
||||||
|
void validate() const;
|
||||||
|
share_type calculate_fee(const fee_parameters_type &k) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::custom_permission_create_operation::fee_parameters_type, (fee))
|
||||||
|
FC_REFLECT(graphene::chain::custom_permission_create_operation, (fee)(owner_account)(permission_name)(auth))
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::custom_permission_update_operation::fee_parameters_type, (fee))
|
||||||
|
FC_REFLECT(graphene::chain::custom_permission_update_operation, (fee)(permission_id)(new_auth)(owner_account))
|
||||||
|
|
||||||
|
FC_REFLECT(graphene::chain::custom_permission_delete_operation::fee_parameters_type, (fee))
|
||||||
|
FC_REFLECT(graphene::chain::custom_permission_delete_operation, (fee)(permission_id)(owner_account))
|
||||||
|
|
@ -45,6 +45,8 @@
|
||||||
#include <graphene/chain/protocol/event.hpp>
|
#include <graphene/chain/protocol/event.hpp>
|
||||||
#include <graphene/chain/protocol/betting_market.hpp>
|
#include <graphene/chain/protocol/betting_market.hpp>
|
||||||
#include <graphene/chain/protocol/tournament.hpp>
|
#include <graphene/chain/protocol/tournament.hpp>
|
||||||
|
#include <graphene/chain/protocol/custom_permission.hpp>
|
||||||
|
#include <graphene/chain/protocol/custom_account_authority.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -135,7 +137,13 @@ namespace graphene { namespace chain {
|
||||||
ticket_purchase_operation,
|
ticket_purchase_operation,
|
||||||
lottery_reward_operation,
|
lottery_reward_operation,
|
||||||
lottery_end_operation,
|
lottery_end_operation,
|
||||||
sweeps_vesting_claim_operation
|
sweeps_vesting_claim_operation,
|
||||||
|
custom_permission_create_operation,
|
||||||
|
custom_permission_update_operation,
|
||||||
|
custom_permission_delete_operation,
|
||||||
|
custom_account_authority_create_operation,
|
||||||
|
custom_account_authority_update_operation,
|
||||||
|
custom_account_authority_delete_operation
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ namespace graphene { namespace chain {
|
||||||
const flat_set<public_key_type>& available_keys,
|
const flat_set<public_key_type>& available_keys,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
|
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
|
||||||
)const;
|
)const;
|
||||||
|
|
||||||
|
|
@ -148,6 +149,7 @@ namespace graphene { namespace chain {
|
||||||
const chain_id_type& chain_id,
|
const chain_id_type& chain_id,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH )const;
|
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH )const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -162,6 +164,7 @@ namespace graphene { namespace chain {
|
||||||
const flat_set<public_key_type>& available_keys,
|
const flat_set<public_key_type>& available_keys,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
|
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
@ -194,6 +197,7 @@ namespace graphene { namespace chain {
|
||||||
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
|
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH,
|
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH,
|
||||||
bool allow_committe = false,
|
bool allow_committe = false,
|
||||||
const flat_set<account_id_type>& active_aprovals = flat_set<account_id_type>(),
|
const flat_set<account_id_type>& active_aprovals = flat_set<account_id_type>(),
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,8 @@ namespace graphene { namespace chain {
|
||||||
betting_market_group_object_type,
|
betting_market_group_object_type,
|
||||||
betting_market_object_type,
|
betting_market_object_type,
|
||||||
bet_object_type,
|
bet_object_type,
|
||||||
|
custom_permission_object_type,
|
||||||
|
custom_account_authority_object_type,
|
||||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -230,6 +232,8 @@ namespace graphene { namespace chain {
|
||||||
class betting_market_group_object;
|
class betting_market_group_object;
|
||||||
class betting_market_object;
|
class betting_market_object;
|
||||||
class bet_object;
|
class bet_object;
|
||||||
|
class custom_permission_object;
|
||||||
|
class custom_account_authority_object;
|
||||||
|
|
||||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||||
|
|
@ -256,6 +260,8 @@ namespace graphene { namespace chain {
|
||||||
typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type;
|
typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type;
|
||||||
typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type;
|
typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type;
|
||||||
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
||||||
|
typedef object_id< protocol_ids, custom_permission_object_type, custom_permission_object> custom_permission_id_type;
|
||||||
|
typedef object_id< protocol_ids, custom_account_authority_object_type, custom_account_authority_object> custom_account_authority_id_type;
|
||||||
|
|
||||||
// implementation types
|
// implementation types
|
||||||
class global_property_object;
|
class global_property_object;
|
||||||
|
|
@ -436,6 +442,8 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
||||||
(betting_market_group_object_type)
|
(betting_market_group_object_type)
|
||||||
(betting_market_object_type)
|
(betting_market_object_type)
|
||||||
(bet_object_type)
|
(bet_object_type)
|
||||||
|
(custom_permission_object_type)
|
||||||
|
(custom_account_authority_object_type)
|
||||||
(OBJECT_TYPE_COUNT)
|
(OBJECT_TYPE_COUNT)
|
||||||
)
|
)
|
||||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||||
|
|
@ -505,6 +513,8 @@ FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
||||||
|
FC_REFLECT_TYPENAME( graphene::chain::custom_permission_id_type )
|
||||||
|
FC_REFLECT_TYPENAME( graphene::chain::custom_account_authority_id_type )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::void_t, )
|
FC_REFLECT( graphene::chain::void_t, )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,30 @@ struct proposal_operation_hardfork_visitor
|
||||||
FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" );
|
FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()(const custom_permission_create_operation &v) const {
|
||||||
|
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_create_operation not allowed yet!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const custom_permission_update_operation &v) const {
|
||||||
|
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_update_operation not allowed yet!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const custom_permission_delete_operation &v) const {
|
||||||
|
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_delete_operation not allowed yet!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const custom_account_authority_create_operation &v) const {
|
||||||
|
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_create_operation not allowed yet!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const custom_account_authority_update_operation &v) const {
|
||||||
|
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_update_operation not allowed yet!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const custom_account_authority_delete_operation &v) const {
|
||||||
|
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_delete_operation not allowed yet!" );
|
||||||
|
}
|
||||||
|
|
||||||
// loop and self visit in proposals
|
// loop and self visit in proposals
|
||||||
void operator()(const proposal_create_operation &v) const {
|
void operator()(const proposal_create_operation &v) const {
|
||||||
for (const op_wrapper &op : v.proposed_ops)
|
for (const op_wrapper &op : v.proposed_ops)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ bool proposal_object::is_authorized_to_execute(database& db) const
|
||||||
available_key_approvals,
|
available_key_approvals,
|
||||||
[&]( account_id_type id ){ return &id(db).active; },
|
[&]( account_id_type id ){ return &id(db).active; },
|
||||||
[&]( account_id_type id ){ return &id(db).owner; },
|
[&]( account_id_type id ){ return &id(db).owner; },
|
||||||
|
[&]( account_id_type id, const operation& op ){
|
||||||
|
return db.get_account_custom_authorities(id, op); },
|
||||||
db.get_global_properties().parameters.max_authority_depth,
|
db.get_global_properties().parameters.max_authority_depth,
|
||||||
true, /* allow committee */
|
true, /* allow committee */
|
||||||
available_active_approvals,
|
available_active_approvals,
|
||||||
|
|
|
||||||
38
libraries/chain/protocol/custom_account_authority.cpp
Normal file
38
libraries/chain/protocol/custom_account_authority.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <graphene/chain/protocol/custom_account_authority.hpp>
|
||||||
|
#include <graphene/chain/protocol/operations.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
void custom_account_authority_create_operation::validate() const
|
||||||
|
{
|
||||||
|
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||||
|
FC_ASSERT(owner_account != GRAPHENE_TEMP_ACCOUNT && owner_account != GRAPHENE_COMMITTEE_ACCOUNT && owner_account != GRAPHENE_WITNESS_ACCOUNT && owner_account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
|
||||||
|
"Custom permissions and account auths cannot be created for special accounts");
|
||||||
|
FC_ASSERT(valid_from < valid_to, "valid_from should be earlier than valid_to");
|
||||||
|
FC_ASSERT(operation_type >= 0 && operation_type < operation::count(), "operation_type is not valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_account_authority_update_operation::validate() const
|
||||||
|
{
|
||||||
|
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||||
|
FC_ASSERT(owner_account != GRAPHENE_TEMP_ACCOUNT && owner_account != GRAPHENE_COMMITTEE_ACCOUNT && owner_account != GRAPHENE_WITNESS_ACCOUNT && owner_account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
|
||||||
|
"Custom permissions and account auths cannot be created for special accounts");
|
||||||
|
FC_ASSERT(new_valid_from.valid() || new_valid_to.valid(), "Something must be updated");
|
||||||
|
if (new_valid_from && new_valid_to)
|
||||||
|
{
|
||||||
|
FC_ASSERT(*new_valid_from < *new_valid_to, "valid_from should be earlier than valid_to");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_account_authority_delete_operation::validate() const
|
||||||
|
{
|
||||||
|
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||||
|
FC_ASSERT(owner_account != GRAPHENE_TEMP_ACCOUNT && owner_account != GRAPHENE_COMMITTEE_ACCOUNT && owner_account != GRAPHENE_WITNESS_ACCOUNT && owner_account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
|
||||||
|
"Custom permissions and account auths cannot be created for special accounts");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
80
libraries/chain/protocol/custom_permission.cpp
Normal file
80
libraries/chain/protocol/custom_permission.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include <graphene/chain/protocol/custom_permission.hpp>
|
||||||
|
#include <graphene/chain/protocol/operations.hpp>
|
||||||
|
|
||||||
|
namespace graphene
|
||||||
|
{
|
||||||
|
namespace chain
|
||||||
|
{
|
||||||
|
|
||||||
|
bool is_valid_permission_name(const string &name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const size_t len = name.size();
|
||||||
|
// RBAC_MIN_PERMISSION_NAME_LENGTH <= len minimum length check
|
||||||
|
if (len < RBAC_MIN_PERMISSION_NAME_LENGTH)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// len <= RBAC_MAX_PERMISSION_NAME_LENGTH max length check
|
||||||
|
if (len > RBAC_MAX_PERMISSION_NAME_LENGTH)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// First character should be a letter between a-z
|
||||||
|
if (!(name[0] >= 'a' && name[0] <= 'z'))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Any character of a permission name should either be a small case letter a-z or a digit 0-9
|
||||||
|
for (const auto &ch : name)
|
||||||
|
{
|
||||||
|
if (!((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Don't accept active and owner permissions as we already have them by default
|
||||||
|
// This is for removing ambiguity for users, accepting them doesn't create any problems
|
||||||
|
if (name == "active" || name == "owner")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
FC_CAPTURE_AND_RETHROW((name))
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_permission_create_operation::validate() const
|
||||||
|
{
|
||||||
|
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||||
|
FC_ASSERT(is_valid_permission_name(permission_name), "Invalid permission name provided");
|
||||||
|
FC_ASSERT(owner_account != GRAPHENE_TEMP_ACCOUNT && owner_account != GRAPHENE_COMMITTEE_ACCOUNT && owner_account != GRAPHENE_WITNESS_ACCOUNT && owner_account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
|
||||||
|
"Custom permissions and account auths cannot be created for special accounts");
|
||||||
|
FC_ASSERT(!auth.is_impossible(), "Impossible authority threshold auth provided");
|
||||||
|
FC_ASSERT(auth.address_auths.size() == 0, "Only account and key auths supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_permission_update_operation::validate() const
|
||||||
|
{
|
||||||
|
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||||
|
FC_ASSERT(owner_account != GRAPHENE_TEMP_ACCOUNT && owner_account != GRAPHENE_COMMITTEE_ACCOUNT && owner_account != GRAPHENE_WITNESS_ACCOUNT && owner_account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
|
||||||
|
"Custom permissions and account auths cannot be created for special accounts");
|
||||||
|
FC_ASSERT(new_auth.valid(), "Something must be updated");
|
||||||
|
if (new_auth)
|
||||||
|
{
|
||||||
|
FC_ASSERT(!new_auth->is_impossible(), "Impossible authority threshold auth provided");
|
||||||
|
FC_ASSERT(new_auth->address_auths.size() == 0, "Only account and key auths supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_permission_delete_operation::validate() const
|
||||||
|
{
|
||||||
|
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||||
|
FC_ASSERT(owner_account != GRAPHENE_TEMP_ACCOUNT && owner_account != GRAPHENE_COMMITTEE_ACCOUNT && owner_account != GRAPHENE_WITNESS_ACCOUNT && owner_account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
|
||||||
|
"Custom permissions and account auths cannot be created for special accounts");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chain
|
||||||
|
} // namespace graphene
|
||||||
|
|
@ -248,6 +248,7 @@ struct sign_state
|
||||||
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
|
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion_depth,
|
uint32_t max_recursion_depth,
|
||||||
bool allow_committe,
|
bool allow_committe,
|
||||||
const flat_set<account_id_type>& active_aprovals,
|
const flat_set<account_id_type>& active_aprovals,
|
||||||
|
|
@ -257,13 +258,6 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
|
||||||
flat_set<account_id_type> required_owner;
|
flat_set<account_id_type> required_owner;
|
||||||
vector<authority> other;
|
vector<authority> other;
|
||||||
|
|
||||||
for( const auto& op : ops )
|
|
||||||
operation_get_required_authorities( op, required_active, required_owner, other );
|
|
||||||
|
|
||||||
if( !allow_committe )
|
|
||||||
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
|
|
||||||
invalid_committee_approval, "Committee account may only propose transactions" );
|
|
||||||
|
|
||||||
sign_state s(sigs,get_active);
|
sign_state s(sigs,get_active);
|
||||||
s.max_recursion = max_recursion_depth;
|
s.max_recursion = max_recursion_depth;
|
||||||
for( auto& id : active_aprovals )
|
for( auto& id : active_aprovals )
|
||||||
|
|
@ -271,6 +265,35 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
|
||||||
for( auto& id : owner_approvals )
|
for( auto& id : owner_approvals )
|
||||||
s.approved_by.insert( id );
|
s.approved_by.insert( id );
|
||||||
|
|
||||||
|
auto approved_by_custom_authority = [&s, &get_custom](
|
||||||
|
account_id_type account,
|
||||||
|
operation op ) mutable {
|
||||||
|
auto custom_auths = get_custom( account, op );
|
||||||
|
for( const auto& auth : custom_auths )
|
||||||
|
if( s.check_authority( &auth ) ) return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for( const auto& op : ops ) {
|
||||||
|
flat_set<account_id_type> operation_required_active;
|
||||||
|
operation_get_required_authorities( op, operation_required_active, required_owner, other );
|
||||||
|
|
||||||
|
auto itr = operation_required_active.begin();
|
||||||
|
while ( itr != operation_required_active.end() ) {
|
||||||
|
if ( approved_by_custom_authority( *itr, op ) )
|
||||||
|
itr = operation_required_active.erase( itr );
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
|
||||||
|
required_active.insert( operation_required_active.begin(), operation_required_active.end() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !allow_committe )
|
||||||
|
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
|
||||||
|
invalid_committee_approval, "Committee account may only propose transactions" );
|
||||||
|
|
||||||
|
|
||||||
for( const auto& auth : other )
|
for( const auto& auth : other )
|
||||||
{
|
{
|
||||||
GRAPHENE_ASSERT( s.check_authority(&auth), tx_missing_other_auth, "Missing Authority", ("auth",auth)("sigs",sigs) );
|
GRAPHENE_ASSERT( s.check_authority(&auth), tx_missing_other_auth, "Missing Authority", ("auth",auth)("sigs",sigs) );
|
||||||
|
|
@ -325,17 +348,41 @@ set<public_key_type> signed_transaction::get_required_signatures(
|
||||||
const flat_set<public_key_type>& available_keys,
|
const flat_set<public_key_type>& available_keys,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion_depth )const
|
uint32_t max_recursion_depth )const
|
||||||
{
|
{
|
||||||
flat_set<account_id_type> required_active;
|
flat_set<account_id_type> required_active;
|
||||||
flat_set<account_id_type> required_owner;
|
flat_set<account_id_type> required_owner;
|
||||||
vector<authority> other;
|
vector<authority> other;
|
||||||
get_required_authorities( required_active, required_owner, other );
|
|
||||||
|
|
||||||
const flat_set<public_key_type>& signature_keys = get_signature_keys( chain_id );
|
const flat_set<public_key_type>& signature_keys = get_signature_keys( chain_id );
|
||||||
sign_state s( signature_keys, get_active, available_keys );
|
sign_state s( signature_keys, get_active, available_keys );
|
||||||
s.max_recursion = max_recursion_depth;
|
s.max_recursion = max_recursion_depth;
|
||||||
|
|
||||||
|
auto approved_by_custom_authority = [&s, &get_custom](
|
||||||
|
account_id_type account,
|
||||||
|
operation op ) mutable {
|
||||||
|
auto custom_auths = get_custom( account, op );
|
||||||
|
for( const auto& auth : custom_auths )
|
||||||
|
if( s.check_authority( &auth ) ) return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for( const auto& op : operations ) {
|
||||||
|
flat_set<account_id_type> operation_required_active;
|
||||||
|
operation_get_required_authorities( op, operation_required_active, required_owner, other );
|
||||||
|
|
||||||
|
auto itr = operation_required_active.begin();
|
||||||
|
while ( itr != operation_required_active.end() ) {
|
||||||
|
if ( approved_by_custom_authority( *itr, op ) )
|
||||||
|
itr = operation_required_active.erase( itr );
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
|
||||||
|
required_active.insert( operation_required_active.begin(), operation_required_active.end() );
|
||||||
|
}
|
||||||
|
|
||||||
for( const auto& auth : other )
|
for( const auto& auth : other )
|
||||||
s.check_authority(&auth);
|
s.check_authority(&auth);
|
||||||
for( auto& owner : required_owner )
|
for( auto& owner : required_owner )
|
||||||
|
|
@ -359,10 +406,11 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
|
||||||
const flat_set<public_key_type>& available_keys,
|
const flat_set<public_key_type>& available_keys,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion
|
uint32_t max_recursion
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
set< public_key_type > s = get_required_signatures( chain_id, available_keys, get_active, get_owner, max_recursion );
|
set< public_key_type > s = get_required_signatures( chain_id, available_keys, get_active, get_owner, get_custom, max_recursion );
|
||||||
flat_set< public_key_type > result( s.begin(), s.end() );
|
flat_set< public_key_type > result( s.begin(), s.end() );
|
||||||
|
|
||||||
for( const public_key_type& k : s )
|
for( const public_key_type& k : s )
|
||||||
|
|
@ -370,7 +418,7 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
|
||||||
result.erase( k );
|
result.erase( k );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
graphene::chain::verify_authority( operations, result, get_active, get_owner, max_recursion );
|
graphene::chain::verify_authority( operations, result, get_active, get_owner, get_custom, max_recursion );
|
||||||
continue; // element stays erased if verify_authority is ok
|
continue; // element stays erased if verify_authority is ok
|
||||||
}
|
}
|
||||||
catch( const tx_missing_owner_auth& e ) {}
|
catch( const tx_missing_owner_auth& e ) {}
|
||||||
|
|
@ -385,9 +433,10 @@ void signed_transaction::verify_authority(
|
||||||
const chain_id_type& chain_id,
|
const chain_id_type& chain_id,
|
||||||
const std::function<const authority*(account_id_type)>& get_active,
|
const std::function<const authority*(account_id_type)>& get_active,
|
||||||
const std::function<const authority*(account_id_type)>& get_owner,
|
const std::function<const authority*(account_id_type)>& get_owner,
|
||||||
|
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
|
||||||
uint32_t max_recursion )const
|
uint32_t max_recursion )const
|
||||||
{ try {
|
{ try {
|
||||||
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, max_recursion );
|
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, get_custom, max_recursion );
|
||||||
} FC_CAPTURE_AND_RETHROW( (*this) ) }
|
} FC_CAPTURE_AND_RETHROW( (*this) ) }
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -1895,6 +1895,38 @@ class wallet_api
|
||||||
bool is_gpos,
|
bool is_gpos,
|
||||||
bool broadcast);
|
bool broadcast);
|
||||||
|
|
||||||
|
signed_transaction create_custom_permission(string owner,
|
||||||
|
string permission_name,
|
||||||
|
authority auth,
|
||||||
|
bool broadcast = true);
|
||||||
|
signed_transaction update_custom_permission(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
fc::optional<authority> new_auth,
|
||||||
|
bool broadcast = true);
|
||||||
|
signed_transaction delete_custom_permission(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
bool broadcast = true);
|
||||||
|
signed_transaction create_custom_account_authority(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
int operation_type,
|
||||||
|
fc::time_point_sec valid_from,
|
||||||
|
fc::time_point_sec valid_to,
|
||||||
|
bool broadcast = true);
|
||||||
|
signed_transaction update_custom_account_authority(string owner,
|
||||||
|
custom_account_authority_id_type auth_id,
|
||||||
|
fc::optional<fc::time_point_sec> new_valid_from,
|
||||||
|
fc::optional<fc::time_point_sec> new_valid_to,
|
||||||
|
bool broadcast = true);
|
||||||
|
signed_transaction delete_custom_account_authority(string owner,
|
||||||
|
custom_account_authority_id_type auth_id,
|
||||||
|
bool broadcast = true);
|
||||||
|
vector<custom_permission_object> get_custom_permissions(string owner) const;
|
||||||
|
fc::optional<custom_permission_object> get_custom_permission_by_name(string owner, string permission_name) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities(string owner) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_id(custom_permission_id_type permission_id) const;
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_name(string owner, string permission_name) const;
|
||||||
|
vector<authority> get_active_custom_account_authorities_by_operation(string owner, int operation_type) const;
|
||||||
|
|
||||||
void dbg_make_uia(string creator, string symbol);
|
void dbg_make_uia(string creator, string symbol);
|
||||||
void dbg_make_mia(string creator, string symbol);
|
void dbg_make_mia(string creator, string symbol);
|
||||||
void dbg_push_blocks( std::string src_filename, uint32_t count );
|
void dbg_push_blocks( std::string src_filename, uint32_t count );
|
||||||
|
|
@ -2157,4 +2189,16 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(get_all_matched_bets_for_bettor)
|
(get_all_matched_bets_for_bettor)
|
||||||
(buy_ticket)
|
(buy_ticket)
|
||||||
(quit)
|
(quit)
|
||||||
|
(create_custom_permission)
|
||||||
|
(update_custom_permission)
|
||||||
|
(delete_custom_permission)
|
||||||
|
(create_custom_account_authority)
|
||||||
|
(update_custom_account_authority)
|
||||||
|
(delete_custom_account_authority)
|
||||||
|
(get_custom_permissions)
|
||||||
|
(get_custom_permission_by_name)
|
||||||
|
(get_custom_account_authorities)
|
||||||
|
(get_custom_account_authorities_by_permission_id)
|
||||||
|
(get_custom_account_authorities_by_permission_name)
|
||||||
|
(get_active_custom_account_authorities_by_operation)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3242,6 +3242,140 @@ public:
|
||||||
return sign_transaction(tx, broadcast);
|
return sign_transaction(tx, broadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signed_transaction create_custom_permission(string owner,
|
||||||
|
string permission_name,
|
||||||
|
authority auth,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
custom_permission_create_operation create_op;
|
||||||
|
create_op.owner_account = get_account(owner).id;
|
||||||
|
create_op.permission_name = permission_name;
|
||||||
|
create_op.auth = auth;
|
||||||
|
|
||||||
|
signed_transaction tx;
|
||||||
|
tx.operations.push_back(create_op);
|
||||||
|
set_operation_fees(tx, get_global_properties().parameters.current_fees);
|
||||||
|
tx.validate();
|
||||||
|
return sign_transaction(tx, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction update_custom_permission(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
fc::optional<authority> new_auth,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
custom_permission_update_operation update_op;
|
||||||
|
update_op.owner_account = get_account(owner).id;
|
||||||
|
update_op.permission_id = permission_id;
|
||||||
|
update_op.new_auth = new_auth;
|
||||||
|
|
||||||
|
signed_transaction tx;
|
||||||
|
tx.operations.push_back(update_op);
|
||||||
|
set_operation_fees(tx, get_global_properties().parameters.current_fees);
|
||||||
|
tx.validate();
|
||||||
|
return sign_transaction(tx, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction delete_custom_permission(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
custom_permission_delete_operation delete_op;
|
||||||
|
delete_op.owner_account = get_account(owner).id;
|
||||||
|
delete_op.permission_id = permission_id;
|
||||||
|
|
||||||
|
signed_transaction tx;
|
||||||
|
tx.operations.push_back(delete_op);
|
||||||
|
set_operation_fees(tx, get_global_properties().parameters.current_fees);
|
||||||
|
tx.validate();
|
||||||
|
return sign_transaction(tx, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction create_custom_account_authority(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
int operation_type,
|
||||||
|
fc::time_point_sec valid_from,
|
||||||
|
fc::time_point_sec valid_to,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
custom_account_authority_create_operation create_op;
|
||||||
|
create_op.owner_account = get_account(owner).id;
|
||||||
|
create_op.permission_id = permission_id;
|
||||||
|
create_op.operation_type = operation_type;
|
||||||
|
create_op.valid_from = valid_from;
|
||||||
|
create_op.valid_to = valid_to;
|
||||||
|
|
||||||
|
signed_transaction tx;
|
||||||
|
tx.operations.push_back(create_op);
|
||||||
|
set_operation_fees(tx, get_global_properties().parameters.current_fees);
|
||||||
|
tx.validate();
|
||||||
|
return sign_transaction(tx, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction update_custom_account_authority(string owner,
|
||||||
|
custom_account_authority_id_type auth_id,
|
||||||
|
fc::optional<fc::time_point_sec> new_valid_from,
|
||||||
|
fc::optional<fc::time_point_sec> new_valid_to,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
custom_account_authority_update_operation update_op;
|
||||||
|
update_op.owner_account = get_account(owner).id;
|
||||||
|
update_op.auth_id = auth_id;
|
||||||
|
update_op.new_valid_from = new_valid_from;
|
||||||
|
update_op.new_valid_to = new_valid_to;
|
||||||
|
|
||||||
|
signed_transaction tx;
|
||||||
|
tx.operations.push_back(update_op);
|
||||||
|
set_operation_fees(tx, get_global_properties().parameters.current_fees);
|
||||||
|
tx.validate();
|
||||||
|
return sign_transaction(tx, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction delete_custom_account_authority(string owner,
|
||||||
|
custom_account_authority_id_type auth_id,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
custom_account_authority_delete_operation delete_op;
|
||||||
|
delete_op.owner_account = get_account(owner).id;
|
||||||
|
delete_op.auth_id = auth_id;
|
||||||
|
|
||||||
|
signed_transaction tx;
|
||||||
|
tx.operations.push_back(delete_op);
|
||||||
|
set_operation_fees(tx, get_global_properties().parameters.current_fees);
|
||||||
|
tx.validate();
|
||||||
|
return sign_transaction(tx, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_permission_object> get_custom_permissions(string owner) const
|
||||||
|
{
|
||||||
|
return _remote_db->get_custom_permissions(get_account(owner).id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::optional<custom_permission_object> get_custom_permission_by_name(string owner, string permission_name) const
|
||||||
|
{
|
||||||
|
return _remote_db->get_custom_permission_by_name(get_account(owner).id, permission_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities(string owner) const
|
||||||
|
{
|
||||||
|
return _remote_db->get_custom_account_authorities(get_account(owner).id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_id(custom_permission_id_type permission_id) const
|
||||||
|
{
|
||||||
|
return _remote_db->get_custom_account_authorities_by_permission_id(permission_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_name(string owner, string permission_name) const
|
||||||
|
{
|
||||||
|
return _remote_db->get_custom_account_authorities_by_permission_name(get_account(owner).id, permission_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<authority> get_active_custom_account_authorities_by_operation(string owner, int operation_type) const
|
||||||
|
{
|
||||||
|
return _remote_db->get_active_custom_account_authorities_by_operation(get_account(owner).id, operation_type);
|
||||||
|
}
|
||||||
|
|
||||||
void dbg_make_uia(string creator, string symbol)
|
void dbg_make_uia(string creator, string symbol)
|
||||||
{
|
{
|
||||||
asset_options opts;
|
asset_options opts;
|
||||||
|
|
@ -4541,8 +4675,84 @@ signed_transaction wallet_api::approve_proposal(
|
||||||
return my->approve_proposal( fee_paying_account, proposal_id, delta, broadcast );
|
return my->approve_proposal( fee_paying_account, proposal_id, delta, broadcast );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::create_custom_permission(string owner,
|
||||||
|
string permission_name,
|
||||||
|
authority auth,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return my->create_custom_permission(owner, permission_name, auth, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::update_custom_permission(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
fc::optional<authority> new_auth,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return my->update_custom_permission(owner, permission_id, new_auth, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::delete_custom_permission(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return my->delete_custom_permission(owner, permission_id, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::create_custom_account_authority(string owner,
|
||||||
|
custom_permission_id_type permission_id,
|
||||||
|
int operation_type,
|
||||||
|
fc::time_point_sec valid_from,
|
||||||
|
fc::time_point_sec valid_to,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return my->create_custom_account_authority(owner, permission_id, operation_type, valid_from, valid_to, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::update_custom_account_authority(string owner,
|
||||||
|
custom_account_authority_id_type auth_id,
|
||||||
|
fc::optional<fc::time_point_sec> new_valid_from,
|
||||||
|
fc::optional<fc::time_point_sec> new_valid_to,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return my->update_custom_account_authority(owner, auth_id, new_valid_from, new_valid_to, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::delete_custom_account_authority(string owner,
|
||||||
|
custom_account_authority_id_type auth_id,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return my->delete_custom_account_authority(owner, auth_id, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_permission_object> wallet_api::get_custom_permissions(string owner) const
|
||||||
|
{
|
||||||
|
return my->get_custom_permissions(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::optional<custom_permission_object> wallet_api::get_custom_permission_by_name(string owner, string permission_name) const
|
||||||
|
{
|
||||||
|
return my->get_custom_permission_by_name(owner, permission_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> wallet_api::get_custom_account_authorities(string owner) const
|
||||||
|
{
|
||||||
|
return my->get_custom_account_authorities(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> wallet_api::get_custom_account_authorities_by_permission_id(custom_permission_id_type permission_id) const
|
||||||
|
{
|
||||||
|
return my->get_custom_account_authorities_by_permission_id(permission_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<custom_account_authority_object> wallet_api::get_custom_account_authorities_by_permission_name(string owner, string permission_name) const
|
||||||
|
{
|
||||||
|
return my->get_custom_account_authorities_by_permission_name(owner, permission_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<authority> wallet_api::get_active_custom_account_authorities_by_operation(string owner, int operation_type) const
|
||||||
|
{
|
||||||
|
return my->get_active_custom_account_authorities_by_operation(owner, operation_type);
|
||||||
|
}
|
||||||
|
|
||||||
global_property_object wallet_api::get_global_properties() const
|
global_property_object wallet_api::get_global_properties() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@
|
||||||
#include <graphene/chain/tournament_object.hpp>
|
#include <graphene/chain/tournament_object.hpp>
|
||||||
#include <graphene/chain/match_object.hpp>
|
#include <graphene/chain/match_object.hpp>
|
||||||
#include <graphene/chain/game_object.hpp>
|
#include <graphene/chain/game_object.hpp>
|
||||||
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
|
||||||
#include <fc/smart_ref_impl.hpp>
|
#include <fc/smart_ref_impl.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
||||||
|
|
@ -1189,6 +1189,14 @@ BOOST_FIXTURE_TEST_CASE( get_required_signatures_test, database_fixture )
|
||||||
return &(aid(db).owner);
|
return &(aid(db).owner);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
auto get_custom = [&](
|
||||||
|
account_id_type id,
|
||||||
|
const operation& op
|
||||||
|
) -> vector<authority>
|
||||||
|
{
|
||||||
|
return db.get_account_custom_authorities(id, op);
|
||||||
|
} ;
|
||||||
|
|
||||||
auto chk = [&](
|
auto chk = [&](
|
||||||
const signed_transaction& tx,
|
const signed_transaction& tx,
|
||||||
flat_set<public_key_type> available_keys,
|
flat_set<public_key_type> available_keys,
|
||||||
|
|
@ -1196,7 +1204,7 @@ BOOST_FIXTURE_TEST_CASE( get_required_signatures_test, database_fixture )
|
||||||
) -> bool
|
) -> bool
|
||||||
{
|
{
|
||||||
//wdump( (tx)(available_keys) );
|
//wdump( (tx)(available_keys) );
|
||||||
set<public_key_type> result_set = tx.get_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner );
|
set<public_key_type> result_set = tx.get_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
|
||||||
//wdump( (result_set)(ref_set) );
|
//wdump( (result_set)(ref_set) );
|
||||||
return result_set == ref_set;
|
return result_set == ref_set;
|
||||||
} ;
|
} ;
|
||||||
|
|
@ -1303,6 +1311,14 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
|
||||||
return &(aid(db).owner);
|
return &(aid(db).owner);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
auto get_custom = [&](
|
||||||
|
account_id_type id,
|
||||||
|
const operation& op
|
||||||
|
) -> vector<authority>
|
||||||
|
{
|
||||||
|
return db.get_account_custom_authorities(id, op);
|
||||||
|
} ;
|
||||||
|
|
||||||
auto chk = [&](
|
auto chk = [&](
|
||||||
const signed_transaction& tx,
|
const signed_transaction& tx,
|
||||||
flat_set<public_key_type> available_keys,
|
flat_set<public_key_type> available_keys,
|
||||||
|
|
@ -1310,7 +1326,7 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
|
||||||
) -> bool
|
) -> bool
|
||||||
{
|
{
|
||||||
//wdump( (tx)(available_keys) );
|
//wdump( (tx)(available_keys) );
|
||||||
set<public_key_type> result_set = tx.get_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner );
|
set<public_key_type> result_set = tx.get_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
|
||||||
//wdump( (result_set)(ref_set) );
|
//wdump( (result_set)(ref_set) );
|
||||||
return result_set == ref_set;
|
return result_set == ref_set;
|
||||||
} ;
|
} ;
|
||||||
|
|
@ -1322,7 +1338,7 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
|
||||||
) -> bool
|
) -> bool
|
||||||
{
|
{
|
||||||
//wdump( (tx)(available_keys) );
|
//wdump( (tx)(available_keys) );
|
||||||
set<public_key_type> result_set = tx.minimize_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner );
|
set<public_key_type> result_set = tx.minimize_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
|
||||||
//wdump( (result_set)(ref_set) );
|
//wdump( (result_set)(ref_set) );
|
||||||
return result_set == ref_set;
|
return result_set == ref_set;
|
||||||
} ;
|
} ;
|
||||||
|
|
@ -1341,9 +1357,9 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
|
||||||
BOOST_CHECK( chk( tx, { alice_public_key, bob_public_key }, { alice_public_key, bob_public_key } ) );
|
BOOST_CHECK( chk( tx, { alice_public_key, bob_public_key }, { alice_public_key, bob_public_key } ) );
|
||||||
BOOST_CHECK( chk_min( tx, { alice_public_key, bob_public_key }, { alice_public_key } ) );
|
BOOST_CHECK( chk_min( tx, { alice_public_key, bob_public_key }, { alice_public_key } ) );
|
||||||
|
|
||||||
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner ), fc::exception );
|
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom ), fc::exception );
|
||||||
sign( tx, alice_private_key );
|
sign( tx, alice_private_key );
|
||||||
tx.verify_authority( db.get_chain_id(), get_active, get_owner );
|
tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom );
|
||||||
}
|
}
|
||||||
catch(fc::exception& e)
|
catch(fc::exception& e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
1647
tests/tests/custom_permission_tests.cpp
Normal file
1647
tests/tests/custom_permission_tests.cpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue