BitShares-Core  5.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  if( id.type() == vote_id_type::witness && needed_witnesses )
163  --needed_witnesses;
164  else if ( id.type() == vote_id_type::committee && needed_committee )
165  --needed_committee;
166 
167  FC_ASSERT( needed_witnesses == 0 && needed_committee == 0,
168  "May not specify fewer witnesses or committee members than the number voted for.");
169 }
170 
172 {
173  auto core_fee_required = k.basic_fee;
174 
175  if( !is_cheap_name(name) )
176  core_fee_required = k.premium_fee;
177 
178  // Authorities and vote lists can be arbitrarily large, so charge a data fee for big ones
179  auto data_fee = calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
180  core_fee_required += data_fee;
181 
182  return core_fee_required;
183 }
184 
186 {
187  FC_ASSERT( fee.amount >= 0 );
188  FC_ASSERT( is_valid_name( name ) );
189  FC_ASSERT( referrer_percent <= GRAPHENE_100_PERCENT );
190  FC_ASSERT( owner.num_auths() != 0 );
191  FC_ASSERT( owner.address_auths.size() == 0 );
192  FC_ASSERT( active.num_auths() != 0 );
193  FC_ASSERT( active.address_auths.size() == 0 );
194  FC_ASSERT( !owner.is_impossible(), "cannot create an account with an impossible owner authority threshold" );
195  FC_ASSERT( !active.is_impossible(), "cannot create an account with an impossible active authority threshold" );
196  options.validate();
197  if( extensions.value.owner_special_authority.valid() )
198  validate_special_authority( *extensions.value.owner_special_authority );
199  if( extensions.value.active_special_authority.valid() )
200  validate_special_authority( *extensions.value.active_special_authority );
201  if( extensions.value.buyback_options.valid() )
202  {
203  FC_ASSERT( !(extensions.value.owner_special_authority.valid()) );
204  FC_ASSERT( !(extensions.value.active_special_authority.valid()) );
205  FC_ASSERT( owner == authority::null_authority() );
206  FC_ASSERT( active == authority::null_authority() );
207  size_t n_markets = extensions.value.buyback_options->markets.size();
208  FC_ASSERT( n_markets > 0 );
209  for( const asset_id_type& m : extensions.value.buyback_options->markets )
210  {
211  FC_ASSERT( m != extensions.value.buyback_options->asset_to_buy );
212  }
213  }
214 }
215 
217 {
218  auto core_fee_required = k.fee;
219  if( new_options )
220  core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
221  return core_fee_required;
222 }
223 
225 {
226  FC_ASSERT( account != GRAPHENE_TEMP_ACCOUNT );
227  FC_ASSERT( fee.amount >= 0 );
228  FC_ASSERT( account != account_id_type() );
229 
230  bool has_action = (
231  owner.valid()
232  || active.valid()
233  || new_options.valid()
234  || extensions.value.owner_special_authority.valid()
235  || extensions.value.active_special_authority.valid()
236  );
237 
238  FC_ASSERT( has_action );
239 
240  if( owner )
241  {
242  FC_ASSERT( owner->num_auths() != 0 );
243  FC_ASSERT( owner->address_auths.size() == 0 );
244  FC_ASSERT( !owner->is_impossible(), "cannot update an account with an impossible owner authority threshold" );
245  }
246  if( active )
247  {
248  FC_ASSERT( active->num_auths() != 0 );
249  FC_ASSERT( active->address_auths.size() == 0 );
250  FC_ASSERT( !active->is_impossible(), "cannot update an account with an impossible active authority threshold" );
251  }
252 
253  if( new_options )
254  new_options->validate();
255  if( extensions.value.owner_special_authority.valid() )
256  validate_special_authority( *extensions.value.owner_special_authority );
257  if( extensions.value.active_special_authority.valid() )
258  validate_special_authority( *extensions.value.active_special_authority );
259 }
260 
262 {
263  if( upgrade_to_lifetime_member )
264  return k.membership_lifetime_fee;
265  return k.membership_annual_fee;
266 }
267 
269 {
270  FC_ASSERT( fee.amount >= 0 );
271 }
272 
274 {
275  FC_ASSERT( fee.amount >= 0 );
276 }
277 
278 } } // graphene::protocol
279 
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:133
#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)
Definition: api.cpp:56
bool is_cheap_name(const string &n)
Definition: account.cpp:133
Update an existing account.
Definition: account.hpp:136
share_type calculate_fee(const fee_parameters_type &) const
Definition: account.cpp:171
#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH
Definition: config.hpp:32
static authority null_authority()
Definition: authority.hpp:114
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:74
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
share_type calculate_fee(const fee_parameters_type &k) const
Definition: account.cpp:216
share_type calculate_fee(const fee_parameters_type &k) const
Definition: account.cpp:261
transfers the account to another account while clearing the white listIn theory an account can be tra...
Definition: account.hpp:267