BitShares-Core  6.1.0
BitShares blockchain implementation and command-line interface software
account.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and 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  */
25 
26 #include <fc/io/raw.hpp>
27 
28 namespace graphene { namespace protocol {
29 
64 bool is_valid_name( const string& name )
65 { try {
66  const size_t len = name.size();
67 
69  {
70  return false;
71  }
72 
74  {
75  return false;
76  }
77 
78  size_t begin = 0;
79  while( true )
80  {
81  size_t end = name.find_first_of( '.', begin );
82  if( end == std::string::npos )
83  end = len;
84  if( (end - begin) < GRAPHENE_MIN_ACCOUNT_NAME_LENGTH )
85  {
86  return false;
87  }
88  switch( name[begin] )
89  {
90  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
91  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
92  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
93  case 'y': case 'z':
94  break;
95  default:
96  return false;
97  }
98  switch( name[end-1] )
99  {
100  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
101  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
102  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
103  case 'y': case 'z':
104  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
105  case '8': case '9':
106  break;
107  default:
108  return false;
109  }
110  for( size_t i=begin+1; i<end-1; i++ )
111  {
112  switch( name[i] )
113  {
114  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
115  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
116  case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
117  case 'y': case 'z':
118  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
119  case '8': case '9':
120  case '-':
121  break;
122  default:
123  return false;
124  }
125  }
126  if( end == len )
127  break;
128  begin = end+1;
129  }
130  return true;
131 } FC_CAPTURE_AND_RETHROW( (name) ) }
132 
133 bool is_cheap_name( const string& n )
134 {
135  bool v = false;
136  for( auto c : n )
137  {
138  if( c >= '0' && c <= '9' ) return true;
139  if( c == '.' || c == '-' || c == '/' ) return true;
140  switch( c )
141  {
142  case 'a':
143  case 'e':
144  case 'i':
145  case 'o':
146  case 'u':
147  case 'y':
148  v = true;
149  }
150  }
151  if( !v )
152  return true;
153  return false;
154 }
155 
157 {
158  auto needed_witnesses = num_witness;
159  auto needed_committee = num_committee;
160 
161  for( vote_id_type id : votes )
162  {
163  if( id.type() == vote_id_type::witness && needed_witnesses > 0 )
164  --needed_witnesses;
165  else if ( id.type() == vote_id_type::committee && needed_committee > 0 )
166  --needed_committee;
167  }
168 
169  FC_ASSERT( needed_witnesses == 0 && needed_committee == 0,
170  "May not specify fewer witnesses or committee members than the number voted for.");
171 }
172 
174 {
175  auto core_fee_required = k.basic_fee;
176 
177  if( !is_cheap_name(name) )
178  core_fee_required = k.premium_fee;
179 
180  // Authorities and vote lists can be arbitrarily large, so charge a data fee for big ones
181  auto data_fee = calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
182  core_fee_required += data_fee;
183 
184  return core_fee_required;
185 }
186 
188 {
189  FC_ASSERT( fee.amount >= 0 );
190  FC_ASSERT( is_valid_name( name ) );
191  FC_ASSERT( referrer_percent <= GRAPHENE_100_PERCENT );
192  FC_ASSERT( owner.num_auths() != 0 );
193  FC_ASSERT( owner.address_auths.size() == 0 );
194  FC_ASSERT( active.num_auths() != 0 );
195  FC_ASSERT( active.address_auths.size() == 0 );
196  FC_ASSERT( !owner.is_impossible(), "cannot create an account with an impossible owner authority threshold" );
197  FC_ASSERT( !active.is_impossible(), "cannot create an account with an impossible active authority threshold" );
198  options.validate();
199  if( extensions.value.owner_special_authority.valid() )
200  validate_special_authority( *extensions.value.owner_special_authority );
201  if( extensions.value.active_special_authority.valid() )
202  validate_special_authority( *extensions.value.active_special_authority );
203  if( extensions.value.buyback_options.valid() )
204  {
205  FC_ASSERT( !(extensions.value.owner_special_authority.valid()) );
206  FC_ASSERT( !(extensions.value.active_special_authority.valid()) );
207  FC_ASSERT( owner == authority::null_authority() );
208  FC_ASSERT( active == authority::null_authority() );
209  size_t n_markets = extensions.value.buyback_options->markets.size();
210  FC_ASSERT( n_markets > 0 );
211  for( const asset_id_type& m : extensions.value.buyback_options->markets )
212  {
213  FC_ASSERT( m != extensions.value.buyback_options->asset_to_buy );
214  }
215  }
216 }
217 
219 {
220  auto core_fee_required = k.fee;
221  if( new_options )
222  core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
223  return core_fee_required;
224 }
225 
227 {
228  FC_ASSERT( account != GRAPHENE_TEMP_ACCOUNT );
229  FC_ASSERT( fee.amount >= 0 );
230  FC_ASSERT( account != account_id_type() );
231 
232  bool has_action = (
233  owner.valid()
234  || active.valid()
235  || new_options.valid()
236  || extensions.value.owner_special_authority.valid()
237  || extensions.value.active_special_authority.valid()
238  );
239 
240  FC_ASSERT( has_action );
241 
242  if( owner )
243  {
244  FC_ASSERT( owner->num_auths() != 0 );
245  FC_ASSERT( owner->address_auths.size() == 0 );
246  FC_ASSERT( !owner->is_impossible(), "cannot update an account with an impossible owner authority threshold" );
247  }
248  if( active )
249  {
250  FC_ASSERT( active->num_auths() != 0 );
251  FC_ASSERT( active->address_auths.size() == 0 );
252  FC_ASSERT( !active->is_impossible(), "cannot update an account with an impossible active authority threshold" );
253  }
254 
255  if( new_options )
256  new_options->validate();
257  if( extensions.value.owner_special_authority.valid() )
258  validate_special_authority( *extensions.value.owner_special_authority );
259  if( extensions.value.active_special_authority.valid() )
260  validate_special_authority( *extensions.value.active_special_authority );
261 }
262 
264 {
265  if( upgrade_to_lifetime_member )
266  return k.membership_lifetime_fee;
267  return k.membership_annual_fee;
268 }
269 
271 {
272  FC_ASSERT( fee.amount >= 0 );
273 }
274 
276 {
277  FC_ASSERT( fee.amount >= 0 );
278 }
279 
280 } } // graphene::protocol
281 
uint64_t membership_lifetime_fee
the cost to upgrade to a lifetime member
Definition: account.hpp:239
#define GRAPHENE_TEMP_ACCOUNT
Represents the canonical account with WILDCARD authority (anybody can access funds in temp account) ...
Definition: config.hpp:148
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH
Definition: config.hpp:33
uint64_t premium_fee
the cost to register the cheapest non-free account
Definition: account.hpp:94
Manage an account&#39;s membership statusThis operation is used to upgrade an account to a member...
Definition: account.hpp:235
void validate_special_authority(const special_authority &auth)
share_type calculate_fee(const fee_parameters_type &k) const
Definition: account.cpp:218
Definition: api.cpp:48
bool is_cheap_name(const string &n)
Definition: account.cpp:133
Update an existing account.
Definition: account.hpp:136
#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH
Definition: config.hpp:32
static authority null_authority()
Definition: authority.hpp:114
share_type calculate_fee(const fee_parameters_type &k) const
Definition: account.cpp:263
size_t pack_size(const T &v)
Definition: raw.hpp:757
These are the fields which can be updated by the active authority.
Definition: account.hpp:39
flat_set< vote_id_type > votes
Definition: account.hpp:58
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:86
share_type calculate_fee(const fee_parameters_type &) const
Definition: account.cpp:173
An ID for some votable object.
Definition: vote.hpp:51
uint64_t basic_fee
the cost to register the cheapest non-free account
Definition: account.hpp:93
bool is_valid_name(const string &name)
Definition: account.cpp:64
This operation is used to whitelist and blacklist accounts, primarily for transacting in whitelisted ...
Definition: account.hpp:197
transfers the account to another account while clearing the white listIn theory an account can be tra...
Definition: account.hpp:267