Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio_contract.cpp
Go to the documentation of this file.
3
10
17
20
23
24namespace sysio { namespace chain {
25
26
27
29 fc::uint128 _id(tid._hash[3], tid._hash[2]);
30 return (unsigned __int128)_id;
31}
32
34 for(const auto& a : auth.accounts) {
35 auto* acct = context.db.find<account_object, by_name>(a.permission.actor);
36 SYS_ASSERT( acct != nullptr, action_validate_exception,
37 "account '${account}' does not exist",
38 ("account", a.permission.actor)
39 );
40
41 if( a.permission.permission == config::owner_name || a.permission.permission == config::active_name )
42 continue; // account was already checked to exist, so its owner and active permissions should exist
43
44 if( a.permission.permission == config::sysio_code_name ) // virtual sysio.code permission does not really exist but is allowed
45 continue;
46
47 try {
48 context.control.get_authorization_manager().get_permission({a.permission.actor, a.permission.permission});
49 } catch( const permission_query_exception& ) {
51 "permission '${perm}' does not exist",
52 ("perm", a.permission)
53 );
54 }
55 }
56
57 if( context.trx_context.enforce_whiteblacklist && context.control.is_producing_block() ) {
58 for( const auto& p : auth.keys ) {
59 context.control.check_key_list( p.key );
60 }
61 }
62}
63
68 auto create = context.get_action().data_as<newaccount>();
69 try {
70 context.require_authorization(create.creator);
71// context.require_write_lock( config::sysio_auth_scope );
72 auto& authorization = context.control.get_mutable_authorization_manager();
73
74 SYS_ASSERT( validate(create.owner), action_validate_exception, "Invalid owner authority");
75 SYS_ASSERT( validate(create.active), action_validate_exception, "Invalid active authority");
76
77 auto& db = context.db;
78
79 auto name_str = name(create.name).to_string();
80
81 SYS_ASSERT( !create.name.empty(), action_validate_exception, "account name cannot be empty" );
82 SYS_ASSERT( name_str.size() <= 12, action_validate_exception, "account names can only be 12 chars long" );
83
84 // Check if the creator is privileged
85 const auto &creator = db.get<account_metadata_object, by_name>(create.creator);
86 if( !creator.is_privileged() ) {
87 SYS_ASSERT( name_str.find( "sysio." ) != 0, action_validate_exception,
88 "only privileged accounts can have names that start with 'sysio.'" );
89 }
90
91 auto existing_account = db.find<account_object, by_name>(create.name);
92 SYS_ASSERT(existing_account == nullptr, account_name_exists_exception,
93 "Cannot create account named ${name}, as that name is already taken",
94 ("name", create.name));
95
96 db.create<account_object>([&](auto& a) {
97 a.name = create.name;
98 a.creation_date = context.control.pending_block_time();
99 });
100
101 db.create<account_metadata_object>([&](auto& a) {
102 a.name = create.name;
103 });
104
105 for( const auto& auth : { create.owner, create.active } ){
107 }
108
109 const auto& owner_permission = authorization.create_permission( create.name, config::owner_name, 0,
110 std::move(create.owner) );
111 const auto& active_permission = authorization.create_permission( create.name, config::active_name, owner_permission.id,
112 std::move(create.active) );
113
114 context.control.get_mutable_resource_limits_manager().initialize_account(create.name);
115
116 int64_t ram_delta = config::overhead_per_account_ram_bytes;
118 ram_delta += owner_permission.auth.get_billable_size();
119 ram_delta += active_permission.auth.get_billable_size();
120
121 if (auto dm_logger = context.control.get_deep_mind_logger()) {
122 dm_logger->on_ram_trace(RAM_EVENT_ID("${name}", ("name", create.name)), "account", "add", "newaccount");
123 }
124
125 context.add_ram_usage(create.name, ram_delta);
126
127} FC_CAPTURE_AND_RETHROW( (create) ) }
128
130 auto& db = context.db;
131 auto act = context.get_action().data_as<setcode>();
132 context.require_authorization(act.account);
133
134 SYS_ASSERT( act.vmtype == 0, invalid_contract_vm_type, "code should be 0" );
135 SYS_ASSERT( act.vmversion == 0, invalid_contract_vm_version, "version should be 0" );
136
137 fc::sha256 code_hash;
138
139 int64_t code_size = (int64_t)act.code.size();
140
141 if( code_size > 0 ) {
142 code_hash = fc::sha256::hash( act.code.data(), (uint32_t)act.code.size() );
143 wasm_interface::validate(context.control, act.code);
144 }
145
146 const auto& account = db.get<account_metadata_object,by_name>(act.account);
147 bool existing_code = (account.code_hash != digest_type());
148
149 SYS_ASSERT( code_size > 0 || existing_code, set_exact_code, "contract is already cleared" );
150
151 int64_t old_size = 0;
152 int64_t new_size = code_size * config::setcode_ram_bytes_multiplier;
153
154 if( existing_code ) {
155 const code_object& old_code_entry = db.get<code_object, by_code_hash>(boost::make_tuple(account.code_hash, account.vm_type, account.vm_version));
156 SYS_ASSERT( old_code_entry.code_hash != code_hash, set_exact_code,
157 "contract is already running this version of code" );
158 old_size = (int64_t)old_code_entry.code.size() * config::setcode_ram_bytes_multiplier;
159 if( old_code_entry.code_ref_count == 1 ) {
160 db.remove(old_code_entry);
161 context.control.get_wasm_interface().code_block_num_last_used(account.code_hash, account.vm_type, account.vm_version, context.control.head_block_num() + 1);
162 } else {
163 db.modify(old_code_entry, [](code_object& o) {
164 --o.code_ref_count;
165 });
166 }
167 }
168
169 if( code_size > 0 ) {
170 const code_object* new_code_entry = db.find<code_object, by_code_hash>(
171 boost::make_tuple(code_hash, act.vmtype, act.vmversion) );
172 if( new_code_entry ) {
173 db.modify(*new_code_entry, [&](code_object& o) {
174 ++o.code_ref_count;
175 });
176 } else {
177 db.create<code_object>([&](code_object& o) {
178 o.code_hash = code_hash;
179 o.code.assign(act.code.data(), code_size);
180 o.code_ref_count = 1;
181 o.first_block_used = context.control.head_block_num() + 1;
182 o.vm_type = act.vmtype;
183 o.vm_version = act.vmversion;
184 });
185 }
186 }
187
188 db.modify( account, [&]( auto& a ) {
189 a.code_sequence += 1;
190 a.code_hash = code_hash;
191 a.vm_type = act.vmtype;
192 a.vm_version = act.vmversion;
193 a.last_code_update = context.control.pending_block_time();
194 });
195
196 if (new_size != old_size) {
197 if (auto dm_logger = context.control.get_deep_mind_logger()) {
198 const char* operation = "update";
199 if (old_size <= 0) {
200 operation = "add";
201 } else if (new_size <= 0) {
202 operation = "remove";
203 }
204
205 dm_logger->on_ram_trace(RAM_EVENT_ID("${account}", ("account", act.account)), "code", operation, "setcode");
206 }
207
208 context.add_ram_usage( act.account, new_size - old_size );
209 }
210}
211
213 auto& db = context.db;
214 auto act = context.get_action().data_as<setabi>();
215
216 context.require_authorization(act.account);
217
218 const auto& account = db.get<account_object,by_name>(act.account);
219
220 int64_t abi_size = act.abi.size();
221
222 int64_t old_size = (int64_t)account.abi.size();
223 int64_t new_size = abi_size;
224
225 db.modify( account, [&]( auto& a ) {
226 a.abi.assign(act.abi.data(), abi_size);
227 });
228
229 const auto& account_metadata = db.get<account_metadata_object, by_name>(act.account);
230 db.modify( account_metadata, [&]( auto& a ) {
231 a.abi_sequence += 1;
232 });
233
234 if (new_size != old_size) {
235 if (auto dm_logger = context.control.get_deep_mind_logger()) {
236 const char* operation = "update";
237 if (old_size <= 0) {
238 operation = "add";
239 } else if (new_size <= 0) {
240 operation = "remove";
241 }
242
243 dm_logger->on_ram_trace(RAM_EVENT_ID("${account}", ("account", act.account)), "abi", operation, "setabi");
244 }
245
246 context.add_ram_usage( act.account, new_size - old_size );
247 }
248}
249
251
252 auto update = context.get_action().data_as<updateauth>();
253
254 // ** NEW ADDED IF STATEMENT **
255 if( update.permission != name("auth.ext") && update.permission != name("auth.session") ) {
256 context.require_authorization(update.account); // only here to mark the single authority on this action as used
257 }
258
259 auto& authorization = context.control.get_mutable_authorization_manager();
260 auto& db = context.db;
261
262 SYS_ASSERT(!update.permission.empty(), action_validate_exception, "Cannot create authority with empty name");
263 SYS_ASSERT( update.permission.to_string().find( "sysio." ) != 0, action_validate_exception,
264 "Permission names that start with 'sysio.' are reserved" );
265 SYS_ASSERT(update.permission != update.parent, action_validate_exception, "Cannot set an authority as its own parent");
266 db.get<account_object, by_name>(update.account);
268 "Invalid authority: ${auth}", ("auth", update.auth));
269 if( update.permission == config::active_name )
270 SYS_ASSERT(update.parent == config::owner_name, action_validate_exception, "Cannot change active authority's parent from owner", ("update.parent", update.parent) );
271 if (update.permission == config::owner_name)
272 SYS_ASSERT(update.parent.empty(), action_validate_exception, "Cannot change owner authority's parent");
273 else
274 SYS_ASSERT(!update.parent.empty(), action_validate_exception, "Only owner permission can have empty parent" );
275
276 if( update.auth.waits.size() > 0 ) {
277 auto max_delay = context.control.get_global_properties().configuration.max_transaction_delay;
278 SYS_ASSERT( update.auth.waits.back().wait_sec <= max_delay, action_validate_exception,
279 "Cannot set delay longer than max_transacton_delay, which is ${max_delay} seconds",
280 ("max_delay", max_delay) );
281 }
282
284
285
286
287 auto permission = authorization.find_permission({update.account, update.permission});
288
289 // If a parent_id of 0 is going to be used to indicate the absence of a parent, then we need to make sure that the chain
290 // initializes permission_index with a dummy object that reserves the id of 0.
292 if( update.permission != config::owner_name ) {
293 auto& parent = authorization.get_permission({update.account, update.parent});
294 parent_id = parent.id;
295 }
296
297 if( permission ) {
298 SYS_ASSERT(parent_id == permission->parent, action_validate_exception,
299 "Changing parent authority is not currently supported");
300
301
302 int64_t old_size = (int64_t)(config::billable_size_v<permission_object> + permission->auth.get_billable_size());
303
304 authorization.modify_permission( *permission, update.auth );
305
306 int64_t new_size = (int64_t)(config::billable_size_v<permission_object> + permission->auth.get_billable_size());
307
308 if (auto dm_logger = context.control.get_deep_mind_logger()) {
309 dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", permission->id)), "auth", "update", "updateauth_update");
310 }
311
312 context.add_ram_usage( permission->owner, new_size - old_size );
313 } else {
314 const auto& p = authorization.create_permission( update.account, update.permission, parent_id, update.auth );
315
316 int64_t new_size = (int64_t)(config::billable_size_v<permission_object> + p.auth.get_billable_size());
317
318 if (auto dm_logger = context.control.get_deep_mind_logger()) {
319 dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", p.id)), "auth", "add", "updateauth_create");
320 }
321
322 context.add_ram_usage( update.account, new_size );
323 }
324}
325
327// context.require_write_lock( config::sysio_auth_scope );
328
329 auto remove = context.get_action().data_as<deleteauth>();
330 context.require_authorization(remove.account); // only here to mark the single authority on this action as used
331
332 SYS_ASSERT(remove.permission != config::active_name, action_validate_exception, "Cannot delete active authority");
333 SYS_ASSERT(remove.permission != config::owner_name, action_validate_exception, "Cannot delete owner authority");
334
335 auto& authorization = context.control.get_mutable_authorization_manager();
336 auto& db = context.db;
337
338
339
340 { // Check for links to this permission
341 const auto& index = db.get_index<permission_link_index, by_permission_name>();
342 auto range = index.equal_range(boost::make_tuple(remove.account, remove.permission));
343 SYS_ASSERT(range.first == range.second, action_validate_exception,
344 "Cannot delete a linked authority. Unlink the authority first. This authority is linked to ${code}::${type}.",
345 ("code", range.first->code)("type", range.first->message_type));
346 }
347
348 const auto& permission = authorization.get_permission({remove.account, remove.permission});
349 int64_t old_size = config::billable_size_v<permission_object> + permission.auth.get_billable_size();
350
351 if (auto dm_logger = context.control.get_deep_mind_logger()) {
352 dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", permission.id)), "auth", "remove", "deleteauth");
353 }
354
355 authorization.remove_permission( permission );
356
357 context.add_ram_usage( remove.account, -old_size );
358
359}
360
362// context.require_write_lock( config::sysio_auth_scope );
363
364 auto requirement = context.get_action().data_as<linkauth>();
365 try {
366 SYS_ASSERT(!requirement.requirement.empty(), action_validate_exception, "Required permission cannot be empty");
367
368 context.require_authorization(requirement.account); // only here to mark the single authority on this action as used
369
370 auto& db = context.db;
371 const auto *account = db.find<account_object, by_name>(requirement.account);
372 SYS_ASSERT(account != nullptr, account_query_exception,
373 "Failed to retrieve account: ${account}", ("account", requirement.account)); // Redundant?
374 const auto *code = db.find<account_object, by_name>(requirement.code);
375 SYS_ASSERT(code != nullptr, account_query_exception,
376 "Failed to retrieve code for account: ${account}", ("account", requirement.code));
377 if( requirement.requirement != config::sysio_any_name ) {
378 const permission_object* permission = nullptr;
379 if( context.control.is_builtin_activated( builtin_protocol_feature_t::only_link_to_existing_permission ) ) {
380 permission = db.find<permission_object, by_owner>(
381 boost::make_tuple( requirement.account, requirement.requirement )
382 );
383 } else {
384 permission = db.find<permission_object, by_name>(requirement.requirement);
385 }
386
387 SYS_ASSERT(permission != nullptr, permission_query_exception,
388 "Failed to retrieve permission: ${permission}", ("permission", requirement.requirement));
389 }
390
391 auto link_key = boost::make_tuple(requirement.account, requirement.code, requirement.type);
392 auto link = db.find<permission_link_object, by_action_name>(link_key);
393
394 if( link ) {
395 SYS_ASSERT(link->required_permission != requirement.requirement, action_validate_exception,
396 "Attempting to update required authority, but new requirement is same as old");
397 db.modify(*link, [requirement = requirement.requirement](permission_link_object& link) {
398 link.required_permission = requirement;
399 });
400 } else {
401 const auto& l = db.create<permission_link_object>([&requirement](permission_link_object& link) {
402 link.account = requirement.account;
403 link.code = requirement.code;
404 link.message_type = requirement.type;
405 link.required_permission = requirement.requirement;
406 });
407
408 if (auto dm_logger = context.control.get_deep_mind_logger()) {
409 dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", l.id)), "auth_link", "add", "linkauth");
410 }
411
412 context.add_ram_usage(
413 l.account,
415 );
416 }
417
418 } FC_CAPTURE_AND_RETHROW((requirement))
419}
420
422// context.require_write_lock( config::sysio_auth_scope );
423
424 auto& db = context.db;
425 auto unlink = context.get_action().data_as<unlinkauth>();
426
427 context.require_authorization(unlink.account); // only here to mark the single authority on this action as used
428
429 auto link_key = boost::make_tuple(unlink.account, unlink.code, unlink.type);
430 auto link = db.find<permission_link_object, by_action_name>(link_key);
431 SYS_ASSERT(link != nullptr, action_validate_exception, "Attempting to unlink authority, but no link found");
432
433 if (auto dm_logger = context.control.get_deep_mind_logger()) {
434 dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", link->id)), "auth_link", "remove", "unlinkauth");
435 }
436
437 context.add_ram_usage(
438 link->account,
440 );
441
442 db.remove(*link);
443}
444
446 auto cancel = context.get_action().data_as<canceldelay>();
447 context.require_authorization(cancel.canceling_auth.actor); // only here to mark the single authority on this action as used
448
449 const auto& trx_id = cancel.trx_id;
450
451 context.cancel_deferred_transaction(transaction_id_to_sender_id(trx_id), account_name());
452}
453
454} } // namespace sysio::chain
const mie::Vuint & p
Definition bn.cpp:27
std::string name
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
static sha256 hash(const char *d, uint32_t dlen)
Definition sha256.cpp:44
uint64_t _hash[4]
Definition sha256.hpp:100
an implementation of 128 bit unsigned integer
Definition uint128.hpp:22
static void validate(const controller &control, const bytes &code)
#define RAM_EVENT_ID(FORMAT,...)
Definition deep_mind.hpp:27
#define FC_CAPTURE_AND_RETHROW(...)
void apply_sysio_unlinkauth(apply_context &)
void apply_sysio_canceldelay(apply_context &)
void apply_sysio_deleteauth(apply_context &)
void apply_sysio_setcode(apply_context &)
void apply_sysio_updateauth(apply_context &)
void apply_sysio_setabi(apply_context &)
void apply_sysio_linkauth(apply_context &)
void apply_sysio_newaccount(apply_context &)
bool remove(const path &p)
constexpr uint64_t billable_size_v
Definition config.hpp:147
chainbase::shared_multi_index_container< permission_link_object, indexed_by< ordered_unique< tag< by_id >, >, ordered_unique< tag< by_action_name >, composite_key< permission_link_object, BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account), BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, code), > >, ordered_unique< tag< by_permission_name >, composite_key< permission_link_object, BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account), BOOST_MULTI_INDEX_MEMBER(permission_link_object, permission_name, required_permission), > > > > permission_link_index
checksum_type digest_type
Definition types.hpp:237
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension Error decompressing transaction Transaction should have at least one required authority Expired Transaction Invalid Reference Block Duplicate deferred transaction The transaction can not be found Transaction is too big Invalid transaction extension Transaction includes disallowed Transaction exceeded transient resource limit action_validate_exception
unsigned __int128 uint128_t
Definition types.hpp:242
void validate_authority_precondition(const apply_context &context, const authority &auth)
bool validate(const Authority &auth)
uint128_t transaction_id_to_sender_id(const transaction_id_type &tid)
name account_name
Definition types.hpp:120
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
vector< permission_level_weight > accounts
vector< key_weight > keys
Immutable except for fc::from_variant.
Definition name.hpp:43
int l