Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio.system.cpp
Go to the documentation of this file.
3
4#include <sysio/crypto.hpp>
5#include <sysio/dispatcher.hpp>
6
7#include <cmath>
8
9namespace sysiosystem {
10
11 using sysio::current_time_point;
12 using sysio::token;
13
14 double get_continuous_rate(int64_t annual_rate) {
15 return std::log1p(double(annual_rate)/double(100*inflation_precision));
16 }
17
19 :native(s,code,ds),
20 _voters(get_self(), get_self().value),
21 _producers(get_self(), get_self().value),
22 _producers2(get_self(), get_self().value),
23 _global(get_self(), get_self().value),
24 _global2(get_self(), get_self().value),
25 _global3(get_self(), get_self().value),
26 _global4(get_self(), get_self().value),
27 _rammarket(get_self(), get_self().value),
28 _rexpool(get_self(), get_self().value),
29 _rexretpool(get_self(), get_self().value),
30 _rexretbuckets(get_self(), get_self().value),
31 _rexfunds(get_self(), get_self().value),
32 _rexbalance(get_self(), get_self().value),
33 _rexorders(get_self(), get_self().value)
34 {
35 _gstate = _global.exists() ? _global.get() : get_default_parameters();
36 _gstate2 = _global2.exists() ? _global2.get() : sysio_global_state2{};
37 _gstate3 = _global3.exists() ? _global3.get() : sysio_global_state3{};
38 _gstate4 = _global4.exists() ? _global4.get() : get_default_inflation_parameters();
39 }
40
41 sysio_global_state system_contract::get_default_parameters() {
43 get_blockchain_parameters(dp);
44 return dp;
45 }
46
47 sysio_global_state4 system_contract::get_default_inflation_parameters() {
48 sysio_global_state4 gs4;
49 gs4.continuous_rate = get_continuous_rate(default_annual_rate);
50 gs4.inflation_pay_factor = default_inflation_pay_factor;
51 gs4.votepay_factor = default_votepay_factor;
52 return gs4;
53 }
54
55 symbol system_contract::core_symbol()const {
56 const static auto sym = get_core_symbol( _rammarket );
57 return sym;
58 }
59
61 _global.set( _gstate, get_self() );
62 _global2.set( _gstate2, get_self() );
63 _global3.set( _gstate3, get_self() );
64 _global4.set( _gstate4, get_self() );
65 }
66
67 void system_contract::setram( uint64_t max_ram_size ) {
68 require_auth( get_self() );
69
70 check( _gstate.max_ram_size < max_ram_size, "ram may only be increased" );
71 check( max_ram_size < 1024ll*1024*1024*1024*1024, "ram size is unrealistic" );
72 check( max_ram_size > _gstate.total_ram_bytes_reserved, "attempt to set max below reserved" );
73
74 auto delta = int64_t(max_ram_size) - int64_t(_gstate.max_ram_size);
75 auto itr = _rammarket.find(ramcore_symbol.raw());
76
80 _rammarket.modify( itr, same_payer, [&]( auto& m ) {
81 m.base.balance.amount += delta;
82 });
83
84 _gstate.max_ram_size = max_ram_size;
85 }
86
87 void system_contract::update_ram_supply() {
88 auto cbt = sysio::current_block_time();
89
90 if( cbt <= _gstate2.last_ram_increase ) return;
91
92 auto itr = _rammarket.find(ramcore_symbol.raw());
93 auto new_ram = (cbt.slot - _gstate2.last_ram_increase.slot)*_gstate2.new_ram_per_block;
94 _gstate.max_ram_size += new_ram;
95
99 _rammarket.modify( itr, same_payer, [&]( auto& m ) {
100 m.base.balance.amount += new_ram;
101 });
102 _gstate2.last_ram_increase = cbt;
103 }
104
105 void system_contract::setramrate( uint16_t bytes_per_block ) {
106 require_auth( get_self() );
107
108 update_ram_supply();
109 _gstate2.new_ram_per_block = bytes_per_block;
110 }
111
112#ifdef SYSTEM_BLOCKCHAIN_PARAMETERS
113 extern "C" [[sysio::wasm_import]] void set_parameters_packed(const void*, size_t);
114#endif
115
117 require_auth( get_self() );
118 (sysio::blockchain_parameters&)(_gstate) = params;
119 check( 3 <= _gstate.max_authority_depth, "max_authority_depth should be at least 3" );
120#ifndef SYSTEM_BLOCKCHAIN_PARAMETERS
121 set_blockchain_parameters( params );
122#else
123 constexpr size_t param_count = 18;
124 // an upper bound on the serialized size
125 char buf[1 + sizeof(params) + param_count];
126 datastream<char*> stream(buf, sizeof(buf));
127
128 stream << uint8_t(17);
129 stream << uint8_t(0) << params.max_block_net_usage
130 << uint8_t(1) << params.target_block_net_usage_pct
131 << uint8_t(2) << params.max_transaction_net_usage
132 << uint8_t(3) << params.base_per_transaction_net_usage
133 << uint8_t(4) << params.net_usage_leeway
134 << uint8_t(5) << params.context_free_discount_net_usage_num
135 << uint8_t(6) << params.context_free_discount_net_usage_den
136
137 << uint8_t(7) << params.max_block_cpu_usage
138 << uint8_t(8) << params.target_block_cpu_usage_pct
139 << uint8_t(9) << params.max_transaction_cpu_usage
140 << uint8_t(10) << params.min_transaction_cpu_usage
141
142 << uint8_t(11) << params.max_transaction_lifetime
143 << uint8_t(12) << params.deferred_trx_expiration_window
144 << uint8_t(13) << params.max_transaction_delay
145 << uint8_t(14) << params.max_inline_action_size
146 << uint8_t(15) << params.max_inline_action_depth
147 << uint8_t(16) << params.max_authority_depth;
148 if(params.max_action_return_value_size)
149 {
150 stream << uint8_t(17) << params.max_action_return_value_size.value();
151 ++buf[0];
152 }
153
154 set_parameters_packed(buf, stream.tellp());
155#endif
156 }
157
158#ifdef SYSTEM_CONFIGURABLE_WASM_LIMITS
159
160 // The limits on contract WebAssembly modules
161 struct wasm_parameters
162 {
163 uint32_t max_mutable_global_bytes;
164 uint32_t max_table_elements;
165 uint32_t max_section_elements;
166 uint32_t max_linear_memory_init;
167 uint32_t max_func_local_bytes;
168 uint32_t max_nested_structures;
169 uint32_t max_symbol_bytes;
170 uint32_t max_module_bytes;
171 uint32_t max_code_bytes;
172 uint32_t max_pages;
173 uint32_t max_call_depth;
174 };
175
176 static constexpr wasm_parameters default_limits = {
177 .max_mutable_global_bytes = 1024,
178 .max_table_elements = 1024,
179 .max_section_elements = 8192,
180 .max_linear_memory_init = 64*1024,
181 .max_func_local_bytes = 8192,
182 .max_nested_structures = 1024,
183 .max_symbol_bytes = 8192,
184 .max_module_bytes = 20*1024*1024,
185 .max_code_bytes = 20*1024*1024,
186 .max_pages = 528,
187 .max_call_depth = 251
188 };
189
190 static constexpr wasm_parameters high_limits = {
191 .max_mutable_global_bytes = 8192,
192 .max_table_elements = 8192,
193 .max_section_elements = 8192,
194 .max_linear_memory_init = 16*64*1024,
195 .max_func_local_bytes = 8192,
196 .max_nested_structures = 1024,
197 .max_symbol_bytes = 8192,
198 .max_module_bytes = 20*1024*1024,
199 .max_code_bytes = 20*1024*1024,
200 .max_pages = 528,
201 .max_call_depth = 1024
202 };
203
204 extern "C" [[sysio::wasm_import]] void set_wasm_parameters_packed( const void*, size_t );
205
206 void set_wasm_parameters( const wasm_parameters& params )
207 {
208 char buf[sizeof(uint32_t) + sizeof(params)] = {};
209 memcpy(buf + sizeof(uint32_t), &params, sizeof(params));
210 set_wasm_parameters_packed( buf, sizeof(buf) );
211 }
212
213 void system_contract::wasmcfg( const name& settings )
214 {
215 require_auth( get_self() );
216 if( settings == "default"_n || settings == "low"_n )
217 {
218 set_wasm_parameters( default_limits );
219 }
220 else if( settings == "high"_n )
221 {
222 set_wasm_parameters( high_limits );
223 }
224 else
225 {
226 check(false, "Unkown configuration");
227 }
228 }
229
230#endif
231
232 void system_contract::setpriv( const name& account, uint8_t ispriv ) {
233 require_auth( get_self() );
234 set_privileged( account, ispriv );
235 }
236
237 void system_contract::setalimits( const name& account, int64_t ram, int64_t net, int64_t cpu ) {
238 require_auth( get_self() );
239
240 user_resources_table userres( get_self(), account.value );
241 auto ritr = userres.find( account.value );
242 check( ritr == userres.end(), "only supports unlimited accounts" );
243
244 auto vitr = _voters.find( account.value );
245 if( vitr != _voters.end() ) {
246 bool ram_managed = has_field( vitr->flags1, voter_info::flags1_fields::ram_managed );
247 bool net_managed = has_field( vitr->flags1, voter_info::flags1_fields::net_managed );
248 bool cpu_managed = has_field( vitr->flags1, voter_info::flags1_fields::cpu_managed );
249 check( !(ram_managed || net_managed || cpu_managed), "cannot use setalimits on an account with managed resources" );
250 }
251
252 set_resource_limits( account, ram, net, cpu );
253 }
254
255 void system_contract::setacctram( const name& account, const std::optional<int64_t>& ram_bytes ) {
256 require_auth( get_self() );
257
258 int64_t current_ram, current_net, current_cpu;
259 get_resource_limits( account, current_ram, current_net, current_cpu );
260
261 int64_t ram = 0;
262
263 if( !ram_bytes ) {
264 auto vitr = _voters.find( account.value );
265 check( vitr != _voters.end() && has_field( vitr->flags1, voter_info::flags1_fields::ram_managed ),
266 "RAM of account is already unmanaged" );
267
268 user_resources_table userres( get_self(), account.value );
269 auto ritr = userres.find( account.value );
270
271 ram = ram_gift_bytes;
272 if( ritr != userres.end() ) {
273 ram += ritr->ram_bytes;
274 }
275
276 _voters.modify( vitr, same_payer, [&]( auto& v ) {
277 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::ram_managed, false );
278 });
279 } else {
280 check( *ram_bytes >= 0, "not allowed to set RAM limit to unlimited" );
281
282 auto vitr = _voters.find( account.value );
283 if ( vitr != _voters.end() ) {
284 _voters.modify( vitr, same_payer, [&]( auto& v ) {
285 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::ram_managed, true );
286 });
287 } else {
288 _voters.emplace( account, [&]( auto& v ) {
289 v.owner = account;
290 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::ram_managed, true );
291 });
292 }
293
294 ram = *ram_bytes;
295 }
296
297 set_resource_limits( account, ram, current_net, current_cpu );
298 }
299
300 void system_contract::setacctnet( const name& account, const std::optional<int64_t>& net_weight ) {
301 require_auth( get_self() );
302
303 int64_t current_ram, current_net, current_cpu;
304 get_resource_limits( account, current_ram, current_net, current_cpu );
305
306 int64_t net = 0;
307
308 if( !net_weight ) {
309 auto vitr = _voters.find( account.value );
310 check( vitr != _voters.end() && has_field( vitr->flags1, voter_info::flags1_fields::net_managed ),
311 "Network bandwidth of account is already unmanaged" );
312
313 user_resources_table userres( get_self(), account.value );
314 auto ritr = userres.find( account.value );
315
316 if( ritr != userres.end() ) {
317 net = ritr->net_weight.amount;
318 }
319
320 _voters.modify( vitr, same_payer, [&]( auto& v ) {
321 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::net_managed, false );
322 });
323 } else {
324 check( *net_weight >= -1, "invalid value for net_weight" );
325
326 auto vitr = _voters.find( account.value );
327 if ( vitr != _voters.end() ) {
328 _voters.modify( vitr, same_payer, [&]( auto& v ) {
329 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::net_managed, true );
330 });
331 } else {
332 _voters.emplace( account, [&]( auto& v ) {
333 v.owner = account;
334 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::net_managed, true );
335 });
336 }
337
338 net = *net_weight;
339 }
340
341 set_resource_limits( account, current_ram, net, current_cpu );
342 }
343
344 void system_contract::setacctcpu( const name& account, const std::optional<int64_t>& cpu_weight ) {
345 require_auth( get_self() );
346
347 int64_t current_ram, current_net, current_cpu;
348 get_resource_limits( account, current_ram, current_net, current_cpu );
349
350 int64_t cpu = 0;
351
352 if( !cpu_weight ) {
353 auto vitr = _voters.find( account.value );
354 check( vitr != _voters.end() && has_field( vitr->flags1, voter_info::flags1_fields::cpu_managed ),
355 "CPU bandwidth of account is already unmanaged" );
356
357 user_resources_table userres( get_self(), account.value );
358 auto ritr = userres.find( account.value );
359
360 if( ritr != userres.end() ) {
361 cpu = ritr->cpu_weight.amount;
362 }
363
364 _voters.modify( vitr, same_payer, [&]( auto& v ) {
365 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::cpu_managed, false );
366 });
367 } else {
368 check( *cpu_weight >= -1, "invalid value for cpu_weight" );
369
370 auto vitr = _voters.find( account.value );
371 if ( vitr != _voters.end() ) {
372 _voters.modify( vitr, same_payer, [&]( auto& v ) {
373 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::cpu_managed, true );
374 });
375 } else {
376 _voters.emplace( account, [&]( auto& v ) {
377 v.owner = account;
378 v.flags1 = set_field( v.flags1, voter_info::flags1_fields::cpu_managed, true );
379 });
380 }
381
382 cpu = *cpu_weight;
383 }
384
385 set_resource_limits( account, current_ram, current_net, cpu );
386 }
387
388 void system_contract::activate( const sysio::checksum256& feature_digest ) {
389 require_auth( get_self() );
390 preactivate_feature( feature_digest );
391 }
392
393 void system_contract::rmvproducer( const name& producer ) {
394 require_auth( get_self() );
395 auto prod = _producers.find( producer.value );
396 check( prod != _producers.end(), "producer not found" );
397 _producers.modify( prod, same_payer, [&](auto& p) {
398 p.deactivate();
399 });
400 }
401
403 require_auth( get_self() );
404 check( _gstate2.revision < 255, "can not increment revision" ); // prevent wrap around
405 check( revision == _gstate2.revision + 1, "can only increment revision by one" );
406 check( revision <= 1, // set upper bound to greatest revision supported in the code
407 "specified revision is not yet supported by the code" );
408 _gstate2.revision = revision;
409 }
410
411 void system_contract::setinflation( int64_t annual_rate, int64_t inflation_pay_factor, int64_t votepay_factor ) {
412 require_auth(get_self());
413 check(annual_rate >= 0, "annual_rate can't be negative");
414 if ( inflation_pay_factor < pay_factor_precision ) {
415 check( false, "inflation_pay_factor must not be less than " + std::to_string(pay_factor_precision) );
416 }
417 if ( votepay_factor < pay_factor_precision ) {
418 check( false, "votepay_factor must not be less than " + std::to_string(pay_factor_precision) );
419 }
420 _gstate4.continuous_rate = get_continuous_rate(annual_rate);
421 _gstate4.inflation_pay_factor = inflation_pay_factor;
422 _gstate4.votepay_factor = votepay_factor;
423 _global4.set( _gstate4, get_self() );
424 }
425
435 void native::newaccount( const name& creator,
436 const name& new_account_name,
437 ignore<authority> owner,
438 ignore<authority> active ) {
439
440 if( creator != get_self() ) {
441 uint64_t tmp = new_account_name.value >> 4;
442 bool has_dot = false;
443
444 for( uint32_t i = 0; i < 12; ++i ) {
445 has_dot |= !(tmp & 0x1f);
446 tmp >>= 5;
447 }
448 if( has_dot ) { // or is less than 12 characters
449 auto suffix = new_account_name.suffix();
450 if( suffix == new_account_name ) {
451 name_bid_table bids(get_self(), get_self().value);
452 auto current = bids.find( new_account_name.value );
453 check( current != bids.end(), "no active bid for name" );
454 check( current->high_bidder == creator, "only highest bidder can claim" );
455 check( current->high_bid < 0, "auction for name is not closed yet" );
456 bids.erase( current );
457 } else {
458 check( creator == suffix, "only suffix may create this account" );
459 }
460 }
461 }
462
463 user_resources_table userres( get_self(), new_account_name.value );
464
465 userres.emplace( new_account_name, [&]( auto& res ) {
466 res.owner = new_account_name;
467 res.net_weight = asset( 0, system_contract::get_core_symbol() );
468 res.cpu_weight = asset( 0, system_contract::get_core_symbol() );
469 });
470
471 set_resource_limits( new_account_name, 0, 0, 0 );
472 }
473
474 void native::setabi( const name& acnt, const std::vector<char>& abi,
475 const binary_extension<std::string>& memo ) {
476 sysio::multi_index< "abihash"_n, abi_hash > table(get_self(), get_self().value);
477 auto itr = table.find( acnt.value );
478 if( itr == table.end() ) {
479 table.emplace( acnt, [&]( auto& row ) {
480 row.owner = acnt;
481 row.hash = sysio::sha256(const_cast<char*>(abi.data()), abi.size());
482 });
483 } else {
484 table.modify( itr, same_payer, [&]( auto& row ) {
485 row.hash = sysio::sha256(const_cast<char*>(abi.data()), abi.size());
486 });
487 }
488 }
489
490 void system_contract::init( unsigned_int version, const symbol& core ) {
491 require_auth( get_self() );
492 check( version.value == 0, "unsupported version for init action" );
493
494 auto itr = _rammarket.find(ramcore_symbol.raw());
495 check( itr == _rammarket.end(), "system contract has already been initialized" );
496
497 auto system_token_supply = sysio::token::get_supply(token_account, core.code() );
498 check( system_token_supply.symbol == core, "specified core symbol does not exist (precision mismatch)" );
499
500 check( system_token_supply.amount > 0, "system token supply must be greater than 0" );
501 _rammarket.emplace( get_self(), [&]( auto& m ) {
502 m.supply.amount = 100000000000000ll;
503 m.supply.symbol = ramcore_symbol;
504 m.base.balance.amount = int64_t(_gstate.free_ram());
505 m.base.balance.symbol = ram_symbol;
506 m.quote.balance.amount = system_token_supply.amount / 1000;
507 m.quote.balance.symbol = core;
508 });
509
510 token::open_action open_act{ token_account, { {get_self(), active_permission} } };
511 open_act.send( rex_account, core, get_self() );
512 }
513
514 // ** ON NOTIFY OF AUTH.MSG MODIFICATION **
515 void system_contract::onlinkauth(const name& account_name, const name& permission, const sysio::public_key& pub_key) {
516 // Convert pub_key to authority object
517 authority auth;
518 auth.threshold = 1;
519
520 auth.keys.push_back({pub_key, 1});
521
522 // Update auth with special permission.
523 updateauth_action update_auth{ get_self(), { {get_self(), active_permission} } };
524 update_auth.send(account_name, name("auth.ext"), name("owner"), auth, name(""));
525 }
526
527}
const mie::Vuint & p
Definition bn.cpp:27
std::string name
contains only the public point of an elliptic curve key.
symbol(uint8_t p, const char *s)
Definition symbol.hpp:62
sysio::action_wrapper<"open"_n, &token::open > open_action
static asset get_supply(const name &token_contract_account, const symbol_code &sym_code)
void setabi(const name &account, const std::vector< char > &abi, const binary_extension< std::string > &memo)
sysio::action_wrapper<"updateauth"_n, &native::updateauth > updateauth_action
Definition native.hpp:314
void newaccount(const name &creator, const name &name, ignore< authority > owner, ignore< authority > active)
void activate(const sysio::checksum256 &feature_digest)
void setacctram(const name &account, const std::optional< int64_t > &ram_bytes)
void setparams(const blockchain_parameters_t &params)
void onlinkauth(const name &user, const name &permission, const sysio::public_key &pub_key)
system_contract(name s, name code, datastream< const char * > ds)
static constexpr symbol ram_symbol
static constexpr sysio::name token_account
void setinflation(int64_t annual_rate, int64_t inflation_pay_factor, int64_t votepay_factor)
void rmvproducer(const name &producer)
void setram(uint64_t max_ram_size)
void setacctnet(const name &account, const std::optional< int64_t > &net_weight)
static constexpr sysio::name active_permission
static symbol get_core_symbol(name system_account="sysio"_n)
void setramrate(uint16_t bytes_per_block)
void init(unsigned_int version, const symbol &core)
void setacctcpu(const name &account, const std::optional< int64_t > &cpu_weight)
static constexpr symbol ramcore_symbol
void setalimits(const name &account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight)
void updtrevision(uint8_t revision)
static constexpr sysio::name rex_account
void setpriv(const name &account, uint8_t is_priv)
sysio::blockchain_parameters blockchain_parameters_t
sysio::multi_index< "namebids"_n, name_bid, indexed_by<"highbid"_n, const_mem_fun< name_bid, uint64_t, &name_bid::by_high_bid > > > name_bid_table
double get_continuous_rate(int64_t annual_rate)
sysio::multi_index< "userres"_n, user_resources > user_resources_table
#define value
Definition pkcs11.h:157
unsigned short uint16_t
Definition stdint.h:125
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
Immutable except for fc::from_variant.
Definition name.hpp:43
std::vector< key_weight > keys
Definition native.hpp:73
uint8_t revision
used to track version updates in the future.
account_query_db::get_accounts_by_authorizers_params params
char * s
uint8_t buf[2048]
memcpy((char *) pInfo->slotDescription, s, l)