10#include <boost/tuple/tuple_io.hpp>
16namespace sysio {
namespace chain {
28 authorization_index_set::add_indices(_db);
49 const auto& parent = db.
get(
value.parent);
60 value.name = row.name;
61 value.owner = row.owner;
62 value.last_updated = row.last_updated;
63 value.auth = row.auth;
69 SYS_ASSERT(row.owner ==
name(), snapshot_exception,
"Unexpected owner name on reserved permission 0");
70 SYS_ASSERT(row.auth.accounts.size() == 0, snapshot_exception,
"Unexpected auth accounts on reserved permission 0");
71 SYS_ASSERT(row.auth.keys.size() == 0, snapshot_exception,
"Unexpected auth keys on reserved permission 0");
72 SYS_ASSERT(row.auth.waits.size() == 0, snapshot_exception,
"Unexpected auth waits on reserved permission 0");
73 SYS_ASSERT(row.auth.threshold == 0, snapshot_exception,
"Unexpected auth threshold on reserved permission 0");
74 SYS_ASSERT(row.last_updated ==
time_point(), snapshot_exception,
"Unexpected auth last updated on reserved permission 0");
77 const auto& parent = db.
get<
permission_object, by_owner>(boost::make_tuple(row.owner, row.parent));
79 SYS_ASSERT(parent.id != 0, snapshot_exception,
"Unexpected mapping to reserved permission 0");
80 value.parent = parent.id;
86 p.last_used = row.last_used;
88 value.usage_id = usage.id;
97 authorization_index_set::walk_indices([
this, &snapshot](
auto utils ){
98 using section_t =
typename decltype(utils)::index_t::value_type;
101 if (std::is_same<section_t, permission_usage_object>::value) {
105 snapshot->write_section<section_t>([
this](
auto& section ){
106 decltype(utils)::walk(_db, [
this, §ion](
const auto &row ) {
107 section.add_row(row, _db);
114 authorization_index_set::walk_indices([
this, &snapshot](
auto utils ){
115 using section_t =
typename decltype(utils)::index_t::value_type;
118 if (std::is_same<section_t, permission_usage_object>::value) {
122 snapshot->read_section<section_t>([
this](
auto& section ) {
123 bool more = !section.empty();
125 decltype(utils)::create(_db, [
this, §ion, &more](
auto &row ) {
126 more = section.read_row(row, _db);
142 "Unactivated key type used when creating permission");
144 auto creation_time = initial_creation_time;
150 p.last_used = creation_time;
154 p.usage_id = perm_usage.id;
158 p.last_updated = creation_time;
162 dm_logger->on_create_permission(
p);
177 "Unactivated key type used when creating permission");
179 auto creation_time = initial_creation_time;
185 p.last_used = creation_time;
189 p.usage_id = perm_usage.id;
193 p.last_updated = creation_time;
194 p.auth = std::move(auth);
197 dm_logger->on_create_permission(
p);
206 "Unactivated key type used when modifying permission");
211 std::optional<permission_object> old_permission;
220 dm_logger->on_modify_permission(*old_permission, po);
227 auto range = index.equal_range(permission.id);
229 "Cannot remove a permission which has children. Remove the children first.");
234 dm_logger->on_remove_permission(permission);
253 SYS_ASSERT( !level.actor.empty() && !level.permission.empty(), invalid_permission,
"Invalid permission" );
255 }
SYS_RETHROW_EXCEPTIONS( chain::permission_query_exception,
"Failed to retrieve permission: ${level}", (
"level", level) ) }
259 SYS_ASSERT( !level.actor.empty() && !level.permission.empty(), invalid_permission,
"Invalid permission" );
261 }
SYS_RETHROW_EXCEPTIONS( chain::permission_query_exception,
"Failed to retrieve permission: ${level}", (
"level", level) ) }
263 std::optional<permission_name> authorization_manager::lookup_linked_permission(
account_name authorizer_account,
270 auto key = boost::make_tuple(authorizer_account, scope, act_name);
273 if (link ==
nullptr) {
274 boost::get<2>(key) = {};
279 if (link !=
nullptr) {
280 return link->required_permission;
282 return std::optional<permission_name>();
292 if( scope == config::system_account_name ) {
298 unlinkable_min_permission_action,
299 "cannot call lookup_minimum_permission on native actions that are not allowed to be linked to minimum permissions" );
303 std::optional<permission_name> linked_permission = lookup_linked_permission(authorizer_account, scope, act_name);
304 if( !linked_permission )
305 return config::active_name;
307 if( *linked_permission == config::sysio_any_name )
308 return std::optional<permission_name>();
310 return linked_permission;
314 void authorization_manager::check_updateauth_authorization(
const updateauth& update,
318 SYS_ASSERT( auths.size() == 1, irrelevant_auth_exception,
319 "updateauth action should only have one declared authorization" );
320 const auto& auth = auths[0];
323 SYS_ASSERT( (auth.actor == update.
account || auth.actor ==
name(
"sysio")), irrelevant_auth_exception,
324 "the owner of the affected permission needs to be the actor of the declared authorization" );
328 SYS_ASSERT( auth.actor ==
name(
"sysio"), invalid_permission,
"Special permission, only assignable by 'sysio' as a result of 'onlinkauth'" );
331 if( !min_permission ) {
337 irrelevant_auth_exception,
338 "updateauth action declares irrelevant authority '${auth}'; minimum authority is ${min}",
339 (
"auth", auth)(
"min", permission_level{update.account, min_permission->name}) );
343 void authorization_manager::check_deleteauth_authorization(
const deleteauth& del,
344 const vector<permission_level>& auths
347 SYS_ASSERT( auths.size() == 1, irrelevant_auth_exception,
348 "deleteauth action should only have one declared authorization" );
349 const auto& auth = auths[0];
350 SYS_ASSERT( auth.actor == del.account, irrelevant_auth_exception,
351 "the owner of the permission to delete needs to be the actor of the declared authorization" );
353 const auto& min_permission =
get_permission({del.account, del.permission});
357 irrelevant_auth_exception,
358 "updateauth action declares irrelevant authority '${auth}'; minimum authority is ${min}",
359 (
"auth", auth)(
"min", permission_level{min_permission.owner, min_permission.name}) );
362 void authorization_manager::check_linkauth_authorization(
const linkauth& link,
363 const vector<permission_level>& auths
366 SYS_ASSERT( auths.size() == 1, irrelevant_auth_exception,
367 "link action should only have one declared authorization" );
368 const auto& auth = auths[0];
369 SYS_ASSERT( auth.actor == link.account, irrelevant_auth_exception,
370 "the owner of the linked permission needs to be the actor of the declared authorization" );
372 if( link.code == config::system_account_name
376 "Cannot link sysio::updateauth to a minimum permission" );
378 "Cannot link sysio::deleteauth to a minimum permission" );
380 "Cannot link sysio::linkauth to a minimum permission" );
382 "Cannot link sysio::unlinkauth to a minimum permission" );
384 "Cannot link sysio::canceldelay to a minimum permission" );
389 if( !linked_permission_name )
394 irrelevant_auth_exception,
395 "link action declares irrelevant authority '${auth}'; minimum authority is ${min}",
396 (
"auth", auth)(
"min", permission_level{link.account, *linked_permission_name}) );
399 void authorization_manager::check_unlinkauth_authorization(
const unlinkauth& unlink,
400 const vector<permission_level>& auths
403 SYS_ASSERT( auths.size() == 1, irrelevant_auth_exception,
404 "unlink action should only have one declared authorization" );
405 const auto& auth = auths[0];
406 SYS_ASSERT( auth.actor == unlink.account, irrelevant_auth_exception,
407 "the owner of the linked permission needs to be the actor of the declared authorization" );
409 const auto unlinked_permission_name = lookup_linked_permission(unlink.account, unlink.code, unlink.type);
411 "cannot unlink non-existent permission link of account '${account}' for actions matching '${code}::${action}'",
412 (
"account", unlink.account)(
"code", unlink.code)(
"action", unlink.type) );
414 if( *unlinked_permission_name == config::sysio_any_name )
419 irrelevant_auth_exception,
420 "unlink action declares irrelevant authority '${auth}'; minimum authority is ${min}",
421 (
"auth", auth)(
"min", permission_level{unlink.account, *unlinked_permission_name}) );
424 fc::microseconds authorization_manager::check_canceldelay_authorization(
const canceldelay& cancel,
425 const vector<permission_level>& auths
428 SYS_ASSERT( auths.size() == 1, irrelevant_auth_exception,
429 "canceldelay action should only have one declared authorization" );
430 const auto& auth = auths[0];
434 irrelevant_auth_exception,
435 "canceldelay action declares irrelevant authority '${auth}'; specified authority to satisfy is ${min}",
436 (
"auth", auth)(
"min", cancel.canceling_auth) );
438 const auto& trx_id = cancel.trx_id;
441 const auto& generated_index = generated_transaction_idx.indices().get<by_trx_id>();
442 const auto& itr = generated_index.lower_bound(trx_id);
445 "cannot cancel trx_id=${tid}, there is no deferred transaction with that transaction id",
450 for(
const auto& act : trx.actions ) {
451 for(
const auto& auth : act.authorization ) {
452 if( auth == cancel.canceling_auth ) {
461 "canceling_auth in canceldelay action was not found as authorization in the original delayed transaction" );
463 return (itr->delay_until - itr->published);
472 const flat_set<public_key_type>& provided_keys,
473 const flat_set<permission_level>& provided_permissions,
475 const std::function<
void()>& _checktime,
476 bool allow_unused_keys,
477 bool check_but_dont_fail,
478 const flat_set<permission_level>& satisfied_authorizations
481 const auto& checktime = (
static_cast<bool>(_checktime) ? _checktime :
_noop_checktime );
490 provided_permissions,
491 effective_provided_delay,
495 map<permission_level, fc::microseconds> permissions_to_satisfy;
497 for(
const auto& act : actions ) {
498 bool special_case =
false;
501 if( act.account == config::system_account_name ) {
505 check_updateauth_authorization( act.data_as<
updateauth>(), act.authorization );
507 check_deleteauth_authorization( act.data_as<
deleteauth>(), act.authorization );
509 check_linkauth_authorization( act.data_as<
linkauth>(), act.authorization );
511 check_unlinkauth_authorization( act.data_as<
unlinkauth>(), act.authorization );
513 delay = std::max( delay, check_canceldelay_authorization(act.data_as<
canceldelay>(), act.authorization) );
515 special_case =
false;
519 for(
const auto& declared_auth : act.authorization ) {
523 if( !special_case ) {
525 if( min_permission_name ) {
526 const auto& min_permission =
get_permission({declared_auth.actor, *min_permission_name});
529 irrelevant_auth_exception,
530 "action declares irrelevant authority '${auth}'; minimum authority is ${min}",
531 (
"auth", declared_auth)(
"min",
permission_level{min_permission.owner, min_permission.name}) );
535 if( satisfied_authorizations.find( declared_auth ) == satisfied_authorizations.end() ) {
536 auto res = permissions_to_satisfy.emplace( declared_auth, delay );
537 if( !res.second && res.first->second > delay) {
538 res.first->second =
delay;
551 for(
const auto&
p : permissions_to_satisfy ) {
553 SYS_ASSERT( checker.satisfied(
p.first,
p.second ) || check_but_dont_fail, unsatisfied_authorization,
554 "transaction declares authority '${auth}', "
555 "but does not have signatures for it under a provided delay of ${provided_delay} ms, "
556 "provided permissions ${provided_permissions}, provided keys ${provided_keys}, "
557 "and a delay max limit of ${delay_max_limit_ms} ms",
559 (
"provided_delay", provided_delay.
count()/1000)
560 (
"provided_permissions", provided_permissions)
561 (
"provided_keys", provided_keys)
562 (
"delay_max_limit_ms", delay_max_limit.count()/1000)
567 if( !allow_unused_keys || check_but_dont_fail) {
568 SYS_ASSERT( checker.all_keys_used(), tx_irrelevant_sig,
569 "transaction bears irrelevant signatures from these keys: ${keys}",
570 (
"keys", checker.unused_keys()) );
577 const flat_set<public_key_type>& provided_keys,
578 const flat_set<permission_level>& provided_permissions,
580 const std::function<
void()>& _checktime,
581 bool allow_unused_keys
584 const auto& checktime = (
static_cast<bool>(_checktime) ? _checktime :
_noop_checktime );
591 provided_permissions,
596 SYS_ASSERT( checker.satisfied({account, permission}), unsatisfied_authorization,
597 "permission '${auth}' was not satisfied under a provided delay of ${provided_delay} ms, "
598 "provided permissions ${provided_permissions}, provided keys ${provided_keys}, "
599 "and a delay max limit of ${delay_max_limit_ms} ms",
601 (
"provided_delay", provided_delay.
count()/1000)
602 (
"provided_permissions", provided_permissions)
603 (
"provided_keys", provided_keys)
604 (
"delay_max_limit_ms", delay_max_limit.count()/1000)
607 if( !allow_unused_keys ) {
608 SYS_ASSERT( checker.all_keys_used(), tx_irrelevant_sig,
609 "irrelevant keys provided: ${keys}",
610 (
"keys", checker.unused_keys()) );
615 const flat_set<public_key_type>& candidate_keys,
627 for (
const auto& act : trx.
actions ) {
628 for (
const auto& declared_auth : act.authorization) {
629 SYS_ASSERT( checker.satisfied(declared_auth), unsatisfied_authorization,
630 "transaction declares authority '${auth}', but does not have signatures for it.",
631 (
"auth", declared_auth) );
635 return checker.used_keys();
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
#define SYS_RETHROW_EXCEPTIONS(exception_type, FORMAT,...)
const generic_index< MultiIndexType > & get_index() const
void modify(const ObjectType &obj, Modifier &&m)
const ObjectType * find(CompatibleKey &&key) const
void remove(const ObjectType &obj)
const ObjectType & create(Constructor &&con)
generic_index< MultiIndexType > & get_mutable_index()
const ObjectType & get(CompatibleKey &&key) const
constexpr int64_t count() const
static constexpr microseconds maximum()
authorization_manager(controller &c, chainbase::database &d)
fc::time_point get_permission_last_used(const permission_object &permission) const
static std::function< void()> _noop_checktime
void add_to_snapshot(const snapshot_writer_ptr &snapshot) const
void initialize_database()
std::optional< permission_name > lookup_minimum_permission(account_name authorizer_account, scope_name code_account, action_name type) const
Find the lowest authority level required for authorizer_account to authorize a message of the specifi...
void update_permission_usage(const permission_object &permission)
void read_from_snapshot(const snapshot_reader_ptr &snapshot)
void check_authorization(const vector< action > &actions, const flat_set< public_key_type > &provided_keys, const flat_set< permission_level > &provided_permissions=flat_set< permission_level >(), fc::microseconds provided_delay=fc::microseconds(0), const std::function< void()> &checktime=std::function< void()>(), bool allow_unused_keys=false, bool check_but_dont_fail=false, const flat_set< permission_level > &satisfied_authorizations=flat_set< permission_level >()) const
Check authorizations of a vector of actions with provided keys, permission levels,...
const permission_object & get_permission(const permission_level &level) const
void remove_permission(const permission_object &permission)
const permission_object & create_permission(account_name account, permission_name name, permission_id_type parent, const authority &auth, time_point initial_creation_time=time_point())
const permission_object * find_permission(const permission_level &level) const
void modify_permission(const permission_object &permission, const authority &auth)
flat_set< public_key_type > get_required_keys(const transaction &trx, const flat_set< public_key_type > &candidate_keys, fc::microseconds provided_delay=fc::microseconds(0)) const
permission_object::id_type permission_id_type
const global_property_object & get_global_properties() const
const chainbase::database & db() const
deep_mind_handler * get_deep_mind_logger() const
bool is_builtin_activated(builtin_protocol_feature_t f) const
time_point pending_block_time() const
chain_config configuration
The permission_link_object class assigns permission_objects to message types.
Maintains global state information about consensus protocol rules.
uint32_t num_supported_key_types
#define FC_CAPTURE_AND_RETHROW(...)
void delay(websocketpp::connection_hdl, long duration)
void unpack(Stream &s, std::deque< T > &value)
constexpr microseconds seconds(int64_t s)
constexpr std::size_t get_index()
chainbase::shared_multi_index_container< permission_link_object, indexed_by< ordered_unique< tag< by_id >, >, ordered_unique< tag< by_action_name >, composite_key< permission_link_object, BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account), BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, code), > >, ordered_unique< tag< by_permission_name >, composite_key< permission_link_object, BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account), BOOST_MULTI_INDEX_MEMBER(permission_link_object, permission_name, required_permission), > > > > permission_link_index
@ fix_linkauth_restriction
chainbase::shared_multi_index_container< permission_object, indexed_by< ordered_unique< tag< by_id >, member< permission_object, permission_object::id_type, &permission_object::id > >, ordered_unique< tag< by_parent >, composite_key< permission_object, member< permission_object, permission_object::id_type, &permission_object::parent >, member< permission_object, permission_object::id_type, &permission_object::id > > >, ordered_unique< tag< by_owner >, composite_key< permission_object, member< permission_object, account_name, &permission_object::owner >, member< permission_object, permission_name, &permission_object::name > > >, ordered_unique< tag< by_name >, composite_key< permission_object, member< permission_object, permission_name, &permission_object::name >, member< permission_object, permission_object::id_type, &permission_object::id > > > > > permission_index
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension transaction_exception
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension Error decompressing transaction Transaction should have at least one required authority Expired Transaction Invalid Reference Block Duplicate deferred transaction The transaction can not be found Transaction is too big Invalid transaction extension Transaction includes disallowed Transaction exceeded transient resource limit action_validate_exception
sysio::chain::action_name action_name
std::shared_ptr< snapshot_writer > snapshot_writer_ptr
auto make_auth_checker(PermissionToAuthorityFunc &&pta, uint16_t recursion_depth_limit, const flat_set< public_key_type > &provided_keys, const flat_set< permission_level > &provided_permissions=flat_set< permission_level >(), fc::microseconds provided_delay=fc::microseconds(0), const std::function< void()> &_checktime=std::function< void()>())
authority_checker
chainbase::shared_multi_index_container< generated_transaction_object, indexed_by< ordered_unique< tag< by_id >, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, generated_transaction_object::id_type, id)>, ordered_unique< tag< by_trx_id >, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, transaction_id_type, trx_id)>, ordered_unique< tag< by_expiration >, composite_key< generated_transaction_object, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, time_point, expiration), > >, ordered_unique< tag< by_delay >, composite_key< generated_transaction_object, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, time_point, delay_until), > >, ordered_unique< tag< by_sender_id >, composite_key< generated_transaction_object, BOOST_MULTI_INDEX_MEMBER(generated_transaction_object, account_name, sender), > > > > generated_transaction_multi_index
std::shared_ptr< snapshot_reader > snapshot_reader_ptr
chainbase::shared_multi_index_container< permission_usage_object, indexed_by< ordered_unique< tag< by_id >, member< permission_usage_object, permission_usage_object::id_type, &permission_usage_object::id > > > > permission_usage_index
vector< key_weight > keys
static action_name get_name()
uint32_t max_transaction_delay
the maximum number of seconds that can be imposed as a delay requirement by authorization checks
static action_name get_name()
static snapshot_permission_object to_snapshot_row(const permission_object &value, const chainbase::database &db)
static void from_snapshot_row(snapshot_permission_object &&row, permission_object &value, chainbase::database &db)
static action_name get_name()
Immutable except for fc::from_variant.
name(std::string_view str)
authority auth
authority required to execute this permission
permission_name parent
parent permission
time_point last_updated
the last time this authority was updated
account_name owner
the account this permission belongs to
permission_name name
human-readable name for the permission
time_point last_used
when this permission was last used
static action_name get_name()
permission_name permission
static action_name get_name()