BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
custom_authority_evaluator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
31 
32 namespace graphene { namespace chain {
33 
35 { try {
36  const database& d = db();
37  auto now = d.head_block_time();
38  FC_ASSERT(HARDFORK_BSIP_40_PASSED(now), "Custom active authorities are not yet enabled");
39 
40  op.account(d);
41 
42  const auto& config = d.get_global_properties().parameters.extensions.value.custom_authority_options;
43  FC_ASSERT(config.valid(), "Cannot use custom authorities yet: global configuration not set");
44  FC_ASSERT(op.valid_to > now, "Custom authority expiration must be in the future");
45  FC_ASSERT((op.valid_to - now).to_seconds() <= config->max_custom_authority_lifetime_seconds,
46  "Custom authority lifetime exceeds maximum limit");
47 
48  bool operation_forked_in = hardfork_visitor(now).visit((operation::tag_type)op.operation_type.value);
49  FC_ASSERT(operation_forked_in, "Cannot create custom authority for operation which is not valid yet");
50 
51  auto restriction_count = restriction::restriction_count(op.restrictions);
52  FC_ASSERT(restriction_count <= config->max_custom_authority_restrictions,
53  "Custom authority has more than the maximum number of restrictions");
54 
55  for (const auto& account_weight_pair : op.auth.account_auths)
56  account_weight_pair.first(d);
57 
58  const auto& index = d.get_index_type<custom_authority_index>().indices().get<by_account_custom>();
59  auto range = index.equal_range(op.account);
60  FC_ASSERT(std::distance(range.first, range.second) < config->max_custom_authorities_per_account,
61  "Cannot create custom authority: account already has maximum number");
62  range = index.equal_range(boost::make_tuple(op.account, op.operation_type));
63  FC_ASSERT(std::distance(range.first, range.second) < config->max_custom_authorities_per_account_op,
64  "Cannot create custom authority: account already has maximum number for this operation type");
65 
66  return void_result();
67 } FC_CAPTURE_AND_RETHROW((op)) }
68 
70 { try {
71  database& d = db();
72 
73  return d.create<custom_authority_object>([&op] (custom_authority_object& obj) mutable {
74  obj.account = op.account;
75  obj.enabled = op.enabled;
76  obj.valid_from = op.valid_from;
77  obj.valid_to = op.valid_to;
78  obj.operation_type = op.operation_type;
79  obj.auth = op.auth;
80  std::for_each(op.restrictions.begin(), op.restrictions.end(), [&obj](const restriction& r) mutable {
81  obj.restrictions.insert(std::make_pair(obj.restriction_counter++, r));
82  });
83  }).id;
84 } FC_CAPTURE_AND_RETHROW((op)) }
85 
87 { try {
88  const database& d = db();
89  auto now = d.head_block_time();
90  old_object = &op.authority_to_update(d);
91  FC_ASSERT(old_object->account == op.account, "Cannot update a different account's custom authority");
92 
93  if (op.new_enabled)
94  FC_ASSERT(*op.new_enabled != old_object->enabled,
95  "Custom authority update specifies an enabled flag, but flag is not changed");
96 
97  const auto& config = d.get_global_properties().parameters.extensions.value.custom_authority_options;
98  auto valid_from = old_object->valid_from;
99  auto valid_to = old_object->valid_to;
100  if (op.new_valid_from) {
101  FC_ASSERT(*op.new_valid_from != old_object->valid_from,
102  "Custom authority update specifies a new valid from date, but date is not changed");
103  valid_from = *op.new_valid_from;
104  }
105  if (op.new_valid_to) {
106  FC_ASSERT(*op.new_valid_to != old_object->valid_to,
107  "Custom authority update specifies a new valid to date, but date is not changed");
108  FC_ASSERT(*op.new_valid_to > now, "Custom authority expiration must be in the future");
109  FC_ASSERT((*op.new_valid_to - now).to_seconds() <= config->max_custom_authority_lifetime_seconds,
110  "Custom authority lifetime exceeds maximum limit");
111  valid_to = *op.new_valid_to;
112  }
113  FC_ASSERT(valid_from < valid_to, "Custom authority validity begin date must be before expiration date");
114 
115  if (op.new_auth) {
116  FC_ASSERT(*op.new_auth != old_object->auth,
117  "Custom authority update specifies a new authentication authority, but authority is not changed");
118  for (const auto& account_weight_pair : op.new_auth->account_auths)
119  account_weight_pair.first(d);
120  }
121 
122  std::for_each(op.restrictions_to_remove.begin(), op.restrictions_to_remove.end(), [this](uint16_t id) {
123  FC_ASSERT(old_object->restrictions.count(id) == 1, "Cannot remove restriction ID ${I}: ID not found",
124  ("I", id));
125  });
126  if (!op.restrictions_to_add.empty()) {
127  // Sanity check
128  if (!old_object->restrictions.empty())
129  FC_ASSERT((--old_object->restrictions.end())->first < old_object->restriction_counter,
130  "LOGIC ERROR: Restriction counter overlaps restrictions. Please report this error.");
131  FC_ASSERT(old_object->restriction_counter + op.restrictions_to_add.size() > old_object->restriction_counter,
132  "Unable to add restrictions: causes wraparound of restriction IDs");
133  }
134 
135  // Add up the restriction counts for all old restrictions not being removed, and all new ones
136  size_t restriction_count = 0;
137  for (const auto& restriction_pair : old_object->restrictions)
138  if (op.restrictions_to_remove.count(restriction_pair.first) == 0)
139  restriction_count += restriction_pair.second.restriction_count();
140  restriction_count += restriction::restriction_count(op.restrictions_to_add);
141  // Check restriction count against limit
142  FC_ASSERT(restriction_count <= config->max_custom_authority_restrictions,
143  "Cannot update custom authority: updated authority would exceed the maximum number of restrictions");
144 
145  get_restriction_predicate(op.restrictions_to_add, old_object->operation_type);
146  return void_result();
147 } FC_CAPTURE_AND_RETHROW((op)) }
148 
150 { try {
151  database& d = db();
152 
153  d.modify(*old_object, [&op](custom_authority_object& obj) {
154  if (op.new_enabled) obj.enabled = *op.new_enabled;
155  if (op.new_valid_from) obj.valid_from = *op.new_valid_from;
156  if (op.new_valid_to) obj.valid_to = *op.new_valid_to;
157  if (op.new_auth) obj.auth = *op.new_auth;
158 
159  std::for_each(op.restrictions_to_remove.begin(), op.restrictions_to_remove.end(), [&obj](auto id) mutable {
160  obj.restrictions.erase(id);
161  });
162  std::for_each(op.restrictions_to_add.begin(), op.restrictions_to_add.end(), [&obj](const auto& r) mutable {
163  obj.restrictions.insert(std::make_pair(obj.restriction_counter++, r));
164  });
165 
166  // Clear the predicate cache
167  obj.clear_predicate_cache();
168  });
169 
170  return void_result();
171 } FC_CAPTURE_AND_RETHROW((op)) }
172 
174 { try {
175  const database& d = db();
176 
177  old_object = &op.authority_to_delete(d);
178  FC_ASSERT(old_object->account == op.account, "Cannot delete a different account's custom authority");
179 
180  return void_result();
181 } FC_CAPTURE_AND_RETHROW((op)) }
182 
184 { try {
185  database& d = db();
186 
187  d.remove(*old_object);
188 
189  return void_result();
190 } FC_CAPTURE_AND_RETHROW((op)) }
191 
192 } } // graphene::chain
account_id_type account
Account which owns the custom authority to update; also pays the fee.
custom_authority_id_type authority_to_update
ID of the custom authority to update.
void modify(const T &obj, const Lambda &m)
vector< restriction > restrictions
Restrictions on operations this custom authority can authenticate.
optional< time_point_sec > new_valid_to
Change to the custom authority expiration date.
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:56
account_id_type account
Account which owns the custom authority to update; also pays the fee.
restriction_predicate_function get_restriction_predicate(vector< restriction > rs, operation::tag_type op_type)
get_restriction_predicate Get a predicate function for the supplied restriction
void clear_predicate_cache()
Clear the cache of the predicate function.
optional< bool > new_enabled
Change to whether the custom authority is enabled or not.
bool enabled
Whether the custom authority is enabled or not.
custom_authority_id_type authority_to_delete
ID of the custom authority to delete.
const global_property_object & get_global_properties() const
Definition: db_getter.cpp:44
Tracks account custom authorities.
time_point_sec valid_to
Expiration date for custom authority.
time_point_sec valid_from
Date when custom authority becomes active.
time_point_sec head_block_time() const
Definition: db_getter.cpp:64
fc::static_variant< transfer_operation, limit_order_create_operation, limit_order_cancel_operation, call_order_update_operation, fill_order_operation, account_create_operation, account_update_operation, account_whitelist_operation, account_upgrade_operation, account_transfer_operation, asset_create_operation, asset_update_operation, asset_update_bitasset_operation, asset_update_feed_producers_operation, asset_issue_operation, asset_reserve_operation, asset_fund_fee_pool_operation, asset_settle_operation, asset_global_settle_operation, asset_publish_feed_operation, witness_create_operation, witness_update_operation, proposal_create_operation, proposal_update_operation, proposal_delete_operation, withdraw_permission_create_operation, withdraw_permission_update_operation, withdraw_permission_claim_operation, withdraw_permission_delete_operation, committee_member_create_operation, committee_member_update_operation, committee_member_update_global_parameters_operation, vesting_balance_create_operation, vesting_balance_withdraw_operation, worker_create_operation, custom_operation, assert_operation, balance_claim_operation, override_transfer_operation, transfer_to_blind_operation, blind_transfer_operation, transfer_from_blind_operation, asset_settle_cancel_operation, asset_claim_fees_operation, fba_distribute_operation, bid_collateral_operation, execute_bid_operation, asset_claim_pool_operation, asset_update_issuer_operation, htlc_create_operation, htlc_redeem_operation, htlc_redeemed_operation, htlc_extend_operation, htlc_refund_operation, custom_authority_create_operation, custom_authority_update_operation, custom_authority_delete_operation, ticket_create_operation, ticket_update_operation >::tag_type
int64_t tag_type
flat_map< account_id_type, weight_type > account_auths
Definition: authority.hpp:120
vector< restriction > restrictions_to_add
Vector of new restrictions.
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
optional< authority > new_auth
Change to the authentication for the custom authority.
optional< time_point_sec > new_valid_from
Change to the custom authority begin date.
account_id_type account
Account which is setting the custom authority; also pays the fee.
unsigned_int operation_type
Tag of the operation this custom authority can authorize.
flat_map< uint16_t, restriction > restrictions
The hardfork_visitor struct checks whether a given operation type has been hardforked in or not...
const object & get(object_id_type id) const
Definition: index.hpp:111
uint64_t value
Definition: varint.hpp:17
authority auth
Authentication requirements for the custom authority.
abstract base class for accessing objects indexed in various ways.
Definition: index.hpp:71
void remove(const object &obj)
void for_each(T &&t, const account_object &a, seq< Is... >)
Definition: database.hpp:700
const T & create(F &&constructor)
const IndexType & get_index_type() const
flat_set< uint16_t > restrictions_to_remove
Set of IDs of restrictions to remove.