Skip to content

Commit 91bbacc

Browse files
BSIP 40: Finish writing operations
Notably, I made an overhaul to the fee logic here. The old logic was incredibly complex and had weird multiply-by-zero edge cases to get a free fee... I dropped the whole thing and replaced it with a simple price per byte, which should have a fairly similar effect without segfaulting anyone's brain.
1 parent 438f81b commit 91bbacc

File tree

8 files changed

+129
-256
lines changed

8 files changed

+129
-256
lines changed

libraries/protocol/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ list(APPEND SOURCES account.cpp
1717
authority.cpp
1818
special_authority.cpp
1919
custom_authority.cpp
20-
restriction.cpp
2120
restriction_predicate.cpp
2221
committee_member.cpp
2322
custom.cpp

libraries/protocol/custom_authority.cpp

+35-76
Original file line numberDiff line numberDiff line change
@@ -23,100 +23,59 @@
2323
*/
2424
#include <graphene/protocol/custom_authority.hpp>
2525
#include <graphene/protocol/operations.hpp>
26+
#include <graphene/protocol/restriction_predicate.hpp>
2627

2728
namespace graphene { namespace protocol {
2829

29-
share_type custom_authority_create_operation::calculate_fee( const fee_parameters_type& k )const
30-
{
30+
share_type custom_authority_create_operation::calculate_fee(const fee_parameters_type& k)const {
3131
share_type core_fee_required = k.basic_fee;
32-
33-
if( enabled )
34-
{
35-
share_type unit_fee = k.price_per_k_unit;
36-
unit_fee *= (valid_to - valid_from).to_seconds();
37-
unit_fee *= auth.num_auths();
38-
uint64_t restriction_units = 0;
39-
for( const auto& r : restrictions )
40-
{
41-
restriction_units += r.get_units();
42-
}
43-
unit_fee *= restriction_units;
44-
unit_fee /= 1000;
45-
core_fee_required += unit_fee;
46-
}
47-
32+
core_fee_required += k.price_per_byte * (fc::raw::pack_size(restrictions) + fc::raw::pack_size(auth));
4833
return core_fee_required;
4934
}
5035

51-
void custom_authority_create_operation::validate()const
52-
{
53-
FC_ASSERT( fee.amount >= 0, "Fee amount can not be negative" );
36+
void custom_authority_create_operation::validate()const {
37+
FC_ASSERT(fee.amount >= 0, "Fee amount can not be negative");
5438

55-
FC_ASSERT( account != GRAPHENE_TEMP_ACCOUNT
56-
&& account != GRAPHENE_COMMITTEE_ACCOUNT
57-
&& account != GRAPHENE_WITNESS_ACCOUNT
58-
&& account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
59-
"Can not create custom authority for special accounts" );
39+
FC_ASSERT(account != GRAPHENE_TEMP_ACCOUNT
40+
&& account != GRAPHENE_COMMITTEE_ACCOUNT
41+
&& account != GRAPHENE_WITNESS_ACCOUNT
42+
&& account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
43+
"Can not create custom authority for special accounts");
6044

61-
FC_ASSERT( valid_from < valid_to, "valid_from must be earlier than valid_to" );
45+
FC_ASSERT(valid_from < valid_to, "valid_from must be earlier than valid_to");
6246

63-
// Note: when adding new operation with hard fork, need to check more strictly in evaluator
64-
// TODO add code in evaluator
65-
FC_ASSERT( operation_type.value < operation::count(), "operation_type is too large" );
47+
// Note: The authentication authority can be empty, but it cannot be impossible to satisify. Disable the authority
48+
// using the `enabled` boolean rather than setting an impossible authority.
6649

67-
// Note: allow auths to be empty
68-
//FC_ASSERT( auth.num_auths() > 0, "Can not set empty auth" );
69-
FC_ASSERT( auth.address_auths.size() == 0, "Address auth is not supported" );
70-
// Note: allow auths to be impossible
71-
//FC_ASSERT( !auth.is_impossible(), "cannot use an imposible authority threshold" );
50+
FC_ASSERT(auth.address_auths.size() == 0, "Address authorities are not supported");
51+
FC_ASSERT(!auth.is_impossible(), "Cannot use an imposible authority threshold");
7252

73-
// Note: allow restrictions to be empty
74-
for( const auto& r: restrictions )
75-
{
76-
// recursively validate member index and argument type
77-
r.validate( operation_type );
78-
}
53+
// Validate restrictions by constructing a predicate for them; this throws if restrictions aren't valid
54+
get_restriction_predicate(restrictions, operation_type);
7955
}
8056

81-
share_type custom_authority_update_operation::calculate_fee( const fee_parameters_type& k )const
82-
{
57+
share_type custom_authority_update_operation::calculate_fee(const fee_parameters_type& k)const {
8358
share_type core_fee_required = k.basic_fee;
84-
85-
share_type unit_fee = k.price_per_k_unit;
86-
unit_fee *= delta_units;
87-
unit_fee /= 1000;
88-
89-
return core_fee_required + unit_fee;
59+
core_fee_required += k.price_per_byte * fc::raw::pack_size(restrictions_to_add);
60+
if (new_auth)
61+
core_fee_required += k.price_per_byte * fc::raw::pack_size(*new_auth);
62+
return core_fee_required;
9063
}
9164

92-
void custom_authority_update_operation::validate()const
93-
{
94-
FC_ASSERT( fee.amount >= 0, "Fee amount can not be negative" );
95-
96-
FC_ASSERT( account != GRAPHENE_TEMP_ACCOUNT
97-
&& account != GRAPHENE_COMMITTEE_ACCOUNT
98-
&& account != GRAPHENE_WITNESS_ACCOUNT
99-
&& account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
100-
"Can not create custom authority for special accounts" );
101-
/*
102-
FC_ASSERT( valid_from < valid_to, "valid_from must be earlier than valid_to" );
103-
// Note: when adding new operation with hard fork, need to check more strictly in evaluator
104-
// TODO add code in evaluator
105-
FC_ASSERT( operation_type < operation::count(), "operation type too large" );
106-
FC_ASSERT( auth.num_auths() > 0, "Can not set empty auth" );
107-
FC_ASSERT( auth.address_auths.size() == 0, "Address auth is not supported" );
108-
//FC_ASSERT( !auth.is_impossible(), "cannot use an imposible authority threshold" );
109-
// Note: allow restrictions to be empty
110-
for( const auto& r : restrictions )
111-
{
112-
// TODO recursively validate member index and argument type
113-
r.validate( operation_type );
65+
void custom_authority_update_operation::validate()const {
66+
FC_ASSERT(fee.amount >= 0, "Fee amount can not be negative");
67+
68+
FC_ASSERT(account != GRAPHENE_TEMP_ACCOUNT
69+
&& account != GRAPHENE_COMMITTEE_ACCOUNT
70+
&& account != GRAPHENE_WITNESS_ACCOUNT
71+
&& account != GRAPHENE_RELAXED_COMMITTEE_ACCOUNT,
72+
"Can not create custom authority for special accounts");
73+
if (new_valid_from && new_valid_to)
74+
FC_ASSERT(*new_valid_from < new_valid_to, "valid_from must be earlier than valid_to");
75+
if (new_auth) {
76+
FC_ASSERT(!new_auth->is_impossible(), "Cannot use an impossible authority threshold");
77+
FC_ASSERT(new_auth->address_auths.size() == 0, "Address auth is not supported");
11478
}
115-
*/
116-
}
117-
118-
void custom_authority_delete_operation::validate()const
119-
{
12079
}
12180

12281
} } // graphene::protocol

libraries/protocol/include/graphene/protocol/authority.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ namespace graphene { namespace protocol {
108108
(a.address_auths == b.address_auths);
109109
}
110110
uint32_t num_auths()const { return account_auths.size() + key_auths.size() + address_auths.size(); }
111-
void clear() { account_auths.clear(); key_auths.clear(); }
111+
void clear() { account_auths.clear(); key_auths.clear(); address_auths.clear(); weight_threshold = 0; }
112112

113113
static authority null_authority()
114114
{

libraries/protocol/include/graphene/protocol/custom_authority.hpp

+70-53
Original file line numberDiff line numberDiff line change
@@ -33,87 +33,104 @@ namespace graphene { namespace protocol {
3333
* @brief Create a new custom authority
3434
* @ingroup operations
3535
*/
36-
struct custom_authority_create_operation : public base_operation
37-
{
38-
struct fee_parameters_type
39-
{
40-
uint64_t basic_fee = GRAPHENE_BLOCKCHAIN_PRECISION;
41-
uint32_t price_per_k_unit = 100; ///< units = valid seconds * items in auth * items in restrictions
36+
struct custom_authority_create_operation : public base_operation {
37+
struct fee_parameters_type {
38+
uint64_t basic_fee = GRAPHENE_BLOCKCHAIN_PRECISION;
39+
uint32_t price_per_byte = GRAPHENE_BLOCKCHAIN_PRECISION / 10;
4240
};
4341

44-
asset fee; // TODO: defer fee to expiration / update / removal ?
45-
account_id_type account;
46-
uint32_t custom_id;
47-
bool enabled;
48-
time_point_sec valid_from;
49-
time_point_sec valid_to;
50-
unsigned_int operation_type;
51-
authority auth;
52-
vector<restriction> restrictions;
42+
/// Operation fee
43+
asset fee;
44+
/// Account which is setting the custom authority; also pays the fee
45+
account_id_type account;
46+
/// Whether the custom authority is enabled or not
47+
bool enabled;
48+
/// Date when custom authority becomes active
49+
time_point_sec valid_from;
50+
/// Expiration date for custom authority
51+
time_point_sec valid_to;
52+
/// Tag of the operation this custom authority can authorize
53+
unsigned_int operation_type;
54+
/// Authentication requirements for the custom authority
55+
authority auth;
56+
/// Restrictions on operations this custom authority can authenticate
57+
vector<restriction> restrictions;
5358

5459
extensions_type extensions;
5560

5661
account_id_type fee_payer()const { return account; }
57-
void validate()const;
58-
share_type calculate_fee(const fee_parameters_type& k)const;
62+
void validate()const;
63+
share_type calculate_fee(const fee_parameters_type& k)const;
5964
};
6065

6166
/**
6267
* @brief Update a custom authority
6368
* @ingroup operations
6469
*/
65-
struct custom_authority_update_operation : public base_operation
66-
{
67-
struct fee_parameters_type
68-
{
69-
uint64_t basic_fee = GRAPHENE_BLOCKCHAIN_PRECISION;
70-
uint32_t price_per_k_unit = 100; ///< units = valid seconds * items in auth * items in restrictions
70+
struct custom_authority_update_operation : public base_operation {
71+
struct fee_parameters_type {
72+
uint64_t basic_fee = GRAPHENE_BLOCKCHAIN_PRECISION;
73+
uint32_t price_per_byte = GRAPHENE_BLOCKCHAIN_PRECISION / 10;
7174
};
7275

73-
asset fee;
74-
account_id_type account;
75-
uint64_t delta_units; // to calculate fee, it will be validated in evaluator
76-
// Note: if start was in the past, when updating, used fee should be deducted
76+
/// Operation fee
77+
asset fee;
78+
/// Account which owns the custom authority to update; also pays the fee
79+
account_id_type account;
80+
/// ID of the custom authority to update
81+
custom_authority_id_type authority_to_update;
82+
/// Change to whether the custom authority is enabled or not
83+
optional<bool> new_enabled;
84+
/// Change to the custom authority begin date
85+
optional<time_point_sec> new_valid_from;
86+
/// Change to the custom authority expiration date
87+
optional<time_point_sec> new_valid_to;
88+
/// Change to the authentication for the custom authority
89+
optional<authority> new_auth;
90+
/// Set of indexes of restrictions to remove
91+
flat_set<uint16_t> restrictions_to_remove;
92+
/// Vector of new restrictions; will be appended to the old list
93+
vector<restriction> restrictions_to_add;
94+
95+
extensions_type extensions;
7796

7897
account_id_type fee_payer()const { return account; }
79-
void validate()const;
80-
share_type calculate_fee(const fee_parameters_type& k)const;
98+
void validate()const;
99+
share_type calculate_fee(const fee_parameters_type& k)const;
81100
};
82101

83102

84103
/**
85104
* @brief Delete a custom authority
86105
* @ingroup operations
87106
*/
88-
struct custom_authority_delete_operation : public base_operation
89-
{
107+
struct custom_authority_delete_operation : public base_operation {
90108
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
91109

92-
asset fee;
93-
account_id_type account;
110+
/// Operation fee
111+
asset fee;
112+
/// Account which owns the custom authority to update; also pays the fee
113+
account_id_type account;
114+
/// ID of the custom authority to delete
115+
custom_authority_id_type authority_to_delete;
116+
117+
extensions_type extensions;
94118

95119
account_id_type fee_payer()const { return account; }
96-
void validate()const;
120+
void validate()const {}
121+
share_type calculate_fee(const fee_parameters_type& k)const { return k.fee; }
97122
};
98123

99124
} } // graphene::protocol
100125

101-
FC_REFLECT( graphene::protocol::custom_authority_create_operation::fee_parameters_type, (basic_fee)(price_per_k_unit) )
102-
FC_REFLECT( graphene::protocol::custom_authority_update_operation::fee_parameters_type, (basic_fee)(price_per_k_unit) )
103-
FC_REFLECT( graphene::protocol::custom_authority_delete_operation::fee_parameters_type, (fee) )
104-
105-
FC_REFLECT( graphene::protocol::custom_authority_create_operation,
106-
(fee)
107-
(account)
108-
(custom_id)
109-
(enabled)
110-
(valid_from)
111-
(valid_to)
112-
(operation_type)
113-
(auth)
114-
(restrictions)
115-
(extensions)
116-
)
117-
118-
FC_REFLECT( graphene::protocol::custom_authority_update_operation, (fee)(account) )
119-
FC_REFLECT( graphene::protocol::custom_authority_delete_operation, (fee)(account) )
126+
FC_REFLECT(graphene::protocol::custom_authority_create_operation::fee_parameters_type, (basic_fee)(price_per_byte))
127+
FC_REFLECT(graphene::protocol::custom_authority_update_operation::fee_parameters_type, (basic_fee)(price_per_byte))
128+
FC_REFLECT(graphene::protocol::custom_authority_delete_operation::fee_parameters_type, (fee))
129+
130+
FC_REFLECT(graphene::protocol::custom_authority_create_operation,
131+
(fee)(account)(enabled)(valid_from)(valid_to)(operation_type)(auth)(restrictions)(extensions))
132+
133+
FC_REFLECT(graphene::protocol::custom_authority_update_operation,
134+
(fee)(account)(authority_to_update)(new_enabled)(new_valid_from)
135+
(new_valid_to)(new_auth)(restrictions_to_remove)(restrictions_to_add)(extensions))
136+
FC_REFLECT(graphene::protocol::custom_authority_delete_operation, (fee)(account)(authority_to_delete)(extensions))

libraries/protocol/include/graphene/protocol/restriction.hpp

-5
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ struct restriction {
101101
restriction() = default;
102102
restriction(const string& member_name, function_type type, const argument_type& argument)
103103
: member_name(member_name), restriction_type(type), argument(argument) {}
104-
105-
uint64_t get_units()const;
106-
107-
/// Validates the restriction with given operation type, to be called by an operation validator
108-
void validate( unsigned_int op_type )const;
109104
};
110105

111106
} } // graphene::protocol

libraries/protocol/include/graphene/protocol/types.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ GRAPHENE_DEFINE_IDS(protocol, protocol_ids, /*protocol objects are not prefixed*
260260
(vesting_balance)
261261
(worker)
262262
(balance)
263-
(htlc))
263+
(htlc)
264+
(custom_authority))
264265

265266
FC_REFLECT(graphene::protocol::public_key_type, (key_data))
266267
FC_REFLECT(graphene::protocol::public_key_type::binary_key, (data)(check))

0 commit comments

Comments
 (0)