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