Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
protocol_feature_manager.cpp
Go to the documentation of this file.
5
6#include <fc/scoped_exit.hpp>
7
8#include <algorithm>
9#include <boost/assign/list_of.hpp>
10
11namespace sysio { namespace chain {
12
13 const std::unordered_map<builtin_protocol_feature_t, builtin_protocol_feature_spec, enum_hash<builtin_protocol_feature_t>>
15 boost::assign::map_list_of<builtin_protocol_feature_t, builtin_protocol_feature_spec>
17 "PREACTIVATE_FEATURE",
18 fc::variant("64fe7df32e9b86be2b296b3f81dfd527f84e82b98e363bc97e40bc7a83733310").as<digest_type>(),
19 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
20/*
21Builtin protocol feature: PREACTIVATE_FEATURE
22
23Adds privileged intrinsic to enable a contract to pre-activate a protocol feature specified by its digest.
24Pre-activated protocol features must be activated in the next block.
25*/
26 {},
27 {time_point{}, false, true} // enabled without preactivation and ready to go at any time
28 } )
30 "ONLY_LINK_TO_EXISTING_PERMISSION",
31 fc::variant("f3c3d91c4603cde2397268bfed4e662465293aab10cd9416db0d442b8cec2949").as<digest_type>(),
32 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
33/*
34Builtin protocol feature: ONLY_LINK_TO_EXISTING_PERMISSION
35
36Disallows linking an action to a non-existing permission.
37*/
38 {}
39 } )
40 ( builtin_protocol_feature_t::replace_deferred, builtin_protocol_feature_spec{
41 "REPLACE_DEFERRED",
42 fc::variant("9908b3f8413c8474ab2a6be149d3f4f6d0421d37886033f27d4759c47a26d944").as<digest_type>(),
43 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
44/*
45Builtin protocol feature: REPLACE_DEFERRED
46
47Fix the problems associated with replacing an existing deferred transaction.
48Also corrects the RAM usage of accounts affected by the replace deferred transaction bug.
49*/
50 {}
51 } )
52 ( builtin_protocol_feature_t::no_duplicate_deferred_id, builtin_protocol_feature_spec{
53 "NO_DUPLICATE_DEFERRED_ID",
54 fc::variant("45967387ee92da70171efd9fefd1ca8061b5efe6f124d269cd2468b47f1575a0").as<digest_type>(),
55 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
56/*
57Builtin protocol feature: NO_DUPLICATE_DEFERRED_ID
58Depends on: REPLACE_DEFERRED
59
60Ensures transactions generated by contracts for deferred execution are adjusted to avoid transaction ID conflicts.
61Also allows a contract to send a deferred transaction in a manner that enables the contract to know the transaction ID ahead of time.
62*/
64 } )
65 ( builtin_protocol_feature_t::fix_linkauth_restriction, builtin_protocol_feature_spec{
66 "FIX_LINKAUTH_RESTRICTION",
67 fc::variant("a98241c83511dc86c857221b9372b4aa7cea3aaebc567a48604e1d3db3557050").as<digest_type>(),
68 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
69/*
70Builtin protocol feature: FIX_LINKAUTH_RESTRICTION
71
72Removes the restriction on sysio::linkauth for non-native actions named one of the five special action names:
73updateauth, deleteauth, linkauth, unlinkauth, or canceldelay.
74*/
75 {}
76 } )
78 "DISALLOW_EMPTY_PRODUCER_SCHEDULE",
79 fc::variant("2853617cec3eabd41881eb48882e6fc5e81a0db917d375057864b3befbe29acd").as<digest_type>(),
80 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
81/*
82Builtin protocol feature: DISALLOW_EMPTY_PRODUCER_SCHEDULE
83
84Disallows proposing an empty producer schedule.
85*/
86 {}
87 } )
88 ( builtin_protocol_feature_t::restrict_action_to_self, builtin_protocol_feature_spec{
89 "RESTRICT_ACTION_TO_SELF",
90 fc::variant("e71b6712188391994c78d8c722c1d42c477cf091e5601b5cf1befd05721a57f3").as<digest_type>(),
91 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
92/*
93Builtin protocol feature: RESTRICT_ACTION_TO_SELF
94
95Disallows bypass of authorization checks by unprivileged contracts when sending inline actions or deferred transactions.
96The original protocol rules allow a bypass of authorization checks for actions sent by a contract to itself.
97This protocol feature removes that bypass.
98*/
99 {}
100 } )
101 ( builtin_protocol_feature_t::only_bill_first_authorizer, builtin_protocol_feature_spec{
102 "ONLY_BILL_FIRST_AUTHORIZER",
103 fc::variant("2f1f13e291c79da5a2bbad259ed7c1f2d34f697ea460b14b565ac33b063b73e2").as<digest_type>(),
104 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
105/*
106Builtin protocol feature: ONLY_BILL_FIRST_AUTHORIZER
107
108Adds CPU and network bandwidth usage to only the first authorizer of a transaction.
109*/
110 {}
111 } )
112 ( builtin_protocol_feature_t::forward_setcode, builtin_protocol_feature_spec{
113 "FORWARD_SETCODE",
114 fc::variant("898082c59f921d0042e581f00a59d5ceb8be6f1d9c7a45b6f07c0e26eaee0222").as<digest_type>(),
115 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
116/*
117Builtin protocol feature: FORWARD_SETCODE
118
119Forward sysio::setcode actions to the WebAssembly code deployed on the sysio account.
120*/
121 {}
122 } )
123 ( builtin_protocol_feature_t::get_sender, builtin_protocol_feature_spec{
124 "GET_SENDER",
125 fc::variant("1eab748b95a2e6f4d7cb42065bdee5566af8efddf01a55a0a8d831b823f8828a").as<digest_type>(),
126 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
127/*
128Builtin protocol feature: GET_SENDER
129
130Allows contracts to determine which account is the sender of an inline action.
131*/
132 {}
133 } )
134 ( builtin_protocol_feature_t::ram_restrictions, builtin_protocol_feature_spec{
135 "RAM_RESTRICTIONS",
136 fc::variant("1812fdb5096fd854a4958eb9d53b43219d114de0e858ce00255bd46569ad2c68").as<digest_type>(),
137 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
138/*
139Builtin protocol feature: RAM_RESTRICTIONS
140
141Modifies the restrictions on operations within actions that increase RAM usage of accounts other than the receiver.
142
143An unprivileged contract responding to a notification:
144is not allowed to schedule a deferred transaction in which the RAM costs are paid by an account other than the receiver;
145but is allowed to execute database operations that increase RAM usage of an account other than the receiver as long as
146the action's net effect on RAM usage for the account is to not increase it.
147
148An unprivileged contract executing an action (but not as a response to a notification):
149is not allowed to schedule a deferred transaction in which the RAM costs are paid by an account other than the receiver
150unless that account authorized the action;
151but is allowed to execute database operations that increase RAM usage of an account other than the receiver as long as
152either the account authorized the action or the action's net effect on RAM usage for the account is to not increase it.
153*/
154 {}
155 } )
156 ( builtin_protocol_feature_t::webauthn_key, builtin_protocol_feature_spec{
157 "WEBAUTHN_KEY",
158 fc::variant("927fdf78c51e77a899f2db938249fb1f8bb38f4e43d9c1f75b190492080cbc34").as<digest_type>(),
159 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
160/*
161Builtin protocol feature: WEBAUTHN_KEY
162
163Enables usage of WebAuthn keys and signatures.
164*/
165 {}
166 } )
167 ( builtin_protocol_feature_t::wtmsig_block_signatures, builtin_protocol_feature_spec{
168 "WTMSIG_BLOCK_SIGNATURES",
169 fc::variant("ab76031cad7a457f4fd5f5fca97a3f03b8a635278e0416f77dcc91eb99a48e10").as<digest_type>(),
170 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
171/*
172Builtin protocol feature: WTMSIG_BLOCK_SIGNATURES
173
174Allows producers to specify a multisig of weighted keys as the authority for signing blocks.
175
176A valid block header:
177is no longer allowed to have a non-empty `new_producers` field;
178must announce new producer schedules using a block header extension with ID `1`.
179
180A valid signed block:
181must continue to have exactly one signature in its `signatures` field;
182and may have additional signatures in a block extension with ID `2`.
183
184Privileged Contracts:
185may continue to use `set_proposed_producers` as they have;
186may use a new `set_proposed_producers_ex` intrinsic to access extended features.
187*/
188 {}
189 } )
190 ( builtin_protocol_feature_t::action_return_value, builtin_protocol_feature_spec{
191 "ACTION_RETURN_VALUE",
192 fc::variant("69b064c5178e2738e144ed6caa9349a3995370d78db29e494b3126ebd9111966").as<digest_type>(),
193 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
194/*
195Builtin protocol feature: ACTION_RETURN_VALUE
196
197Enables new `set_action_return_value` intrinsic which sets a value that is included in action_receipt.
198*/
199 {}
200 } )
201 ( builtin_protocol_feature_t::configurable_wasm_limits, builtin_protocol_feature_spec{
202 "CONFIGURABLE_WASM_LIMITS2",
203 fc::variant("8139e99247b87f18ef7eae99f07f00ea3adf39ed53f4d2da3f44e6aa0bfd7c62").as<digest_type>(),
204 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
205/*
206Builtin protocol feature: CONFIGURABLE_WASM_LIMITS2
207
208Allows privileged contracts to set the constraints on WebAssembly code.
209Includes the behavior of GET_WASM_PARAMETERS_PACKED_FIX and
210also removes an inadvertent restriction on custom sections.
211*/
212 {}
213 } )
214 ( builtin_protocol_feature_t::blockchain_parameters, builtin_protocol_feature_spec{
215 "BLOCKCHAIN_PARAMETERS",
216 fc::variant("70787548dcea1a2c52c913a37f74ce99e6caae79110d7ca7b859936a0075b314").as<digest_type>(),
217 {}
218 } )
219 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
220/*
221Builtin protocol feature: BLOCKCHAIN_PARAMETERS
222
223Allows privileged contracts to get and set subsets of blockchain parameters.
224*/
225 ( builtin_protocol_feature_t::get_code_hash, builtin_protocol_feature_spec{
226 "GET_CODE_HASH",
227 fc::variant("d2596697fed14a0840013647b99045022ae6a885089f35a7e78da7a43ad76ed4").as<digest_type>(),
228 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
229/*
230Builtin protocol feature: GET_CODE_HASH
231
232Enables new `get_code_hash` intrinsic which gets the current code hash of an account.
233*/
234 {}
235 } )
236 ( builtin_protocol_feature_t::crypto_primitives, builtin_protocol_feature_spec{
237 "CRYPTO_PRIMITIVES",
238 fc::variant("68d6405cb8df3de95bd834ebb408196578500a9f818ff62ccc68f60b932f7d82").as<digest_type>(),
239 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
240/*
241Builtin protocol feature: CRYPTO_PRIMITIVES
242
243Adds new cryptographic host functions
244- Big integer modular exponentiation (mod_exp)
245- Add, multiply, and pairing check functions for the alt_bn128 elliptic curve. (alt_bn128_add, alt_bn128_mul, alt_bn128_pair)
246- BLAKE2b F compression function (blake2_f)
247- sha3 hash function (with Keccak256 support)
248- k1_recover (safe ECDSA uncompressed pubkey recover for the secp256k1 curve)
249*/
250 {}
251 } )
252 ( builtin_protocol_feature_t::get_block_num, builtin_protocol_feature_spec{
253 "GET_BLOCK_NUM",
254 fc::variant("e5d7992006e628a38c5e6c28dd55ff5e57ea682079bf41fef9b3cced0f46b491").as<digest_type>(),
255 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
256/*
257Builtin protocol feature: GET_BLOCK_NUM
258
259Enables new `get_block_num` intrinsic which returns the current block number.
260*/
261 {}
262 } )
263 ( builtin_protocol_feature_t::em_key, builtin_protocol_feature_spec{
264 "EM_KEY",
265 fc::variant("44454e39d7192100f75c2e4895be95c0d56226f8a33e886d537c10126f6b1d60").as<digest_type>(),
266 // SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
267/*
268Builtin protocol feature: EM_KEY
269
270Enables usage of EM ( Ethereum Message ) keys and signatures.
271*/
272 {}
273 } )
274 ;
275
276
278 auto itr = builtin_protocol_feature_codenames.find( codename );
279 SYS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
280 "Unsupported builtin_protocol_feature_t passed to builtin_protocol_feature_codename: ${codename}",
281 ("codename", static_cast<uint32_t>(codename)) );
282
283 return itr->second.codename;
284 }
285
287 const digest_type& description_digest,
288 flat_set<digest_type>&& dependencies,
289 const protocol_feature_subjective_restrictions& restrictions )
290 :description_digest( description_digest )
291 ,dependencies( std::move(dependencies) )
292 ,subjective_restrictions( restrictions )
293 ,_type( feature_type )
294 {
295 switch( feature_type ) {
298 break;
299 default:
300 {
301 SYS_THROW( protocol_feature_validation_exception,
302 "Unsupported protocol_feature_t passed to constructor: ${type}",
303 ("type", static_cast<uint32_t>(feature_type)) );
304 }
305 break;
306 }
307 }
308
311 "protocol_feature_activation expects FC to support reflector_init" );
312
315 } else {
316 SYS_THROW( protocol_feature_validation_exception,
317 "Unsupported protocol feature type: ${type}", ("type", protocol_feature_type) );
318 }
319 }
320
321 const char* builtin_protocol_feature::feature_type_string = "builtin";
322
324 const digest_type& description_digest,
325 flat_set<digest_type>&& dependencies,
326 const protocol_feature_subjective_restrictions& restrictions )
327 :protocol_feature_base( protocol_feature_t::builtin, description_digest, std::move(dependencies), restrictions )
328 ,_codename(codename)
329 {
330 auto itr = builtin_protocol_feature_codenames.find( codename );
331 SYS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
332 "Unsupported builtin_protocol_feature_t passed to constructor: ${codename}",
333 ("codename", static_cast<uint32_t>(codename)) );
334
335 builtin_feature_codename = itr->second.codename;
336 }
337
340
341 for( const auto& p : builtin_protocol_feature_codenames ) {
342 if( builtin_feature_codename.compare( p.second.codename ) == 0 ) {
343 _codename = p.first;
344 return;
345 }
346 }
347
348 SYS_THROW( protocol_feature_validation_exception,
349 "Unsupported builtin protocol feature codename: ${codename}",
350 ("codename", builtin_feature_codename) );
351 }
352
353
363
364 fc::variant protocol_feature::to_variant( bool include_subjective_restrictions,
365 fc::mutable_variant_object* additional_fields )const
366 {
367 SYS_ASSERT( builtin_feature, protocol_feature_exception, "not a builtin protocol feature" );
368
370
371 mvo( "feature_digest", feature_digest );
372
373 if( additional_fields ) {
374 for( const auto& e : *additional_fields ) {
375 if( e.key().compare( "feature_digest" ) != 0 )
376 mvo( e.key(), e.value() );
377 }
378 }
379
380 if( include_subjective_restrictions ) {
381 fc::mutable_variant_object subjective_restrictions;
382
383 subjective_restrictions( "enabled", enabled );
384 subjective_restrictions( "preactivation_required", preactivation_required );
385 subjective_restrictions( "earliest_allowed_activation_time", earliest_allowed_activation_time );
386
387 mvo( "subjective_restrictions", std::move( subjective_restrictions ) );
388 }
389
390 mvo( "description_digest", description_digest );
391 mvo( "dependencies", dependencies );
392 mvo( "protocol_feature_type", builtin_protocol_feature::feature_type_string );
393
394 fc::variants specification;
395 auto add_to_specification = [&specification]( const char* key_name, auto&& value ) {
397 obj( "name", key_name );
398 obj( "value", std::forward<decltype(value)>( value ) );
399 specification.emplace_back( std::move(obj) );
400 };
401
402
403 add_to_specification( "builtin_feature_codename", builtin_protocol_feature_codename( *builtin_feature ) );
404
405 mvo( "specification", std::move( specification ) );
406
407 return fc::variant( std::move(mvo) );
408 }
409
414
415
417 protocol_feature_set::is_recognized( const digest_type& feature_digest, time_point now )const {
418 auto itr = _recognized_protocol_features.find( feature_digest );
419
420 if( itr == _recognized_protocol_features.end() )
422
423 if( !itr->enabled )
425
426 if( itr->earliest_allowed_activation_time > now )
428
429 return recognized_t::ready;
430 }
431
432 std::optional<digest_type> protocol_feature_set::get_builtin_digest( builtin_protocol_feature_t feature_codename )const {
433 uint32_t indx = static_cast<uint32_t>( feature_codename );
434
435 if( indx >= _recognized_builtin_protocol_features.size() )
436 return {};
437
439 return {};
440
441 return _recognized_builtin_protocol_features[indx]->feature_digest;
442 }
443
445 auto itr = _recognized_protocol_features.find( feature_digest );
446
447 SYS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
448 "unrecognized protocol feature with digest: ${digest}",
449 ("digest", feature_digest)
450 );
451
452 return *itr;
453 }
454
456 const digest_type& feature_digest,
457 const std::function<bool(const digest_type&)>& validator
458 )const {
459 auto itr = _recognized_protocol_features.find( feature_digest );
460
461 if( itr == _recognized_protocol_features.end() ) return false;
462
463 for( const auto& d : itr->dependencies ) {
464 if( !validator(d) ) return false;
465 }
466
467 return true;
468 }
469
473 const std::function<digest_type(builtin_protocol_feature_t dependency)>& handle_dependency
474 ) {
475 auto itr = builtin_protocol_feature_codenames.find( codename );
476
477 SYS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
478 "Unsupported builtin_protocol_feature_t: ${codename}",
479 ("codename", static_cast<uint32_t>(codename)) );
480
481 flat_set<digest_type> dependencies;
482 dependencies.reserve( itr->second.builtin_dependencies.size() );
483
484 for( const auto& d : itr->second.builtin_dependencies ) {
485 dependencies.insert( handle_dependency( d ) );
486 }
487
488 return {itr->first, itr->second.description_digest, std::move(dependencies), itr->second.subjective_restrictions};
489 }
490
492 auto builtin_itr = builtin_protocol_feature_codenames.find( f._codename );
493 SYS_ASSERT( builtin_itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
494 "Builtin protocol feature has unsupported builtin_protocol_feature_t: ${codename}",
495 ("codename", static_cast<uint32_t>( f._codename )) );
496
497 uint32_t indx = static_cast<uint32_t>( f._codename );
498
499 if( indx < _recognized_builtin_protocol_features.size() ) {
501 protocol_feature_exception,
502 "builtin protocol feature with codename '${codename}' already added",
503 ("codename", f.builtin_feature_codename) );
504 }
505
506 auto feature_digest = f.digest();
507
508 const auto& expected_builtin_dependencies = builtin_itr->second.builtin_dependencies;
509 flat_set<builtin_protocol_feature_t> satisfied_builtin_dependencies;
510 satisfied_builtin_dependencies.reserve( expected_builtin_dependencies.size() );
511
512 for( const auto& d : f.dependencies ) {
513 auto itr = _recognized_protocol_features.find( d );
514 SYS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
515 "builtin protocol feature with codename '${codename}' and digest of ${digest} has a dependency on a protocol feature with digest ${dependency_digest} that is not recognized",
516 ("codename", f.builtin_feature_codename)
517 ("digest", feature_digest)
518 ("dependency_digest", d )
519 );
520
521 if( itr->builtin_feature
522 && expected_builtin_dependencies.find( *itr->builtin_feature )
523 != expected_builtin_dependencies.end() )
524 {
525 satisfied_builtin_dependencies.insert( *itr->builtin_feature );
526 }
527 }
528
529 if( expected_builtin_dependencies.size() > satisfied_builtin_dependencies.size() ) {
530 flat_set<builtin_protocol_feature_t> missing_builtins;
531 missing_builtins.reserve( expected_builtin_dependencies.size() - satisfied_builtin_dependencies.size() );
532 std::set_difference( expected_builtin_dependencies.begin(), expected_builtin_dependencies.end(),
533 satisfied_builtin_dependencies.begin(), satisfied_builtin_dependencies.end(),
534 end_inserter( missing_builtins )
535 );
536
537 vector<string> missing_builtins_with_names;
538 missing_builtins_with_names.reserve( missing_builtins.size() );
539 for( const auto& builtin_codename : missing_builtins ) {
540 auto itr = builtin_protocol_feature_codenames.find( builtin_codename );
542 protocol_feature_exception,
543 "Unexpected error"
544 );
545 missing_builtins_with_names.emplace_back( itr->second.codename );
546 }
547
548 SYS_THROW( protocol_feature_validation_exception,
549 "Not all the builtin dependencies of the builtin protocol feature with codename '${codename}' and digest of ${digest} were satisfied.",
550 ("missing_dependencies", missing_builtins_with_names)
551 );
552 }
553
555 feature_digest,
556 f.description_digest,
557 f.dependencies,
558 f.subjective_restrictions.earliest_allowed_activation_time,
559 f.subjective_restrictions.preactivation_required,
560 f.subjective_restrictions.enabled,
561 f._codename
562 } );
563
564 SYS_ASSERT( res.second, protocol_feature_exception,
565 "builtin protocol feature with codename '${codename}' has a digest of ${digest} but another protocol feature with the same digest has already been added",
566 ("codename", f.builtin_feature_codename)("digest", feature_digest) );
567
568 if( indx >= _recognized_builtin_protocol_features.size() ) {
569 for( auto i =_recognized_builtin_protocol_features.size(); i <= indx; ++i ) {
571 }
572 }
573
575 return *res.first;
576 }
577
578
579
582 std::function<deep_mind_handler*()> get_deep_mind_logger
583 ):_protocol_feature_set( std::move(pfs) ), _get_deep_mind_logger(get_deep_mind_logger)
584 {
586 }
587
589 SYS_ASSERT( !is_initialized(), protocol_feature_exception, "cannot initialize protocol_feature_manager twice" );
590
591
592 auto reset_initialized = fc::make_scoped_exit( [this]() { _initialized = false; } );
593 _initialized = true;
594
595 for( const auto& f : db.get<protocol_state_object>().activated_protocol_features ) {
596 activate_feature( f.feature_digest, f.activation_block_num );
597 }
598
599 reset_initialized.cancel();
600 }
601
603 //SYS_ASSERT( _pfm, protocol_feature_iterator_exception, "cannot dereference singular iterator" );
604 //SYS_ASSERT( _index != end_index, protocol_feature_iterator_exception, "cannot dereference end iterator" );
605 return &*(_pfm->_activated_protocol_features[_index].iterator_to_protocol_feature);
606 }
607
609 SYS_ASSERT( _pfm,
610 protocol_feature_iterator_exception,
611 "called activation_ordinal() on singular iterator"
612 );
613 SYS_ASSERT( _index != end_index,
614 protocol_feature_iterator_exception,
615 "called activation_ordinal() on end iterator"
616 );
617
618 return _index;
619 }
620
622 SYS_ASSERT( _pfm,
623 protocol_feature_iterator_exception,
624 "called activation_block_num() on singular iterator"
625 );
626 SYS_ASSERT( _index != end_index,
627 protocol_feature_iterator_exception,
628 "called activation_block_num() on end iterator"
629 );
630
631 return _pfm->_activated_protocol_features[_index].activation_block_num;
632 }
633
635 SYS_ASSERT( _pfm, protocol_feature_iterator_exception, "cannot increment singular iterator" );
636 SYS_ASSERT( _index != end_index, protocol_feature_iterator_exception, "cannot increment end iterator" );
637
638 ++_index;
639 if( _index >= _pfm->_activated_protocol_features.size() ) {
640 _index = end_index;
641 }
642
643 return *this;
644 }
645
647 SYS_ASSERT( _pfm, protocol_feature_iterator_exception, "cannot decrement singular iterator" );
648 if( _index == end_index ) {
649 SYS_ASSERT( _pfm->_activated_protocol_features.size() > 0,
650 protocol_feature_iterator_exception,
651 "cannot decrement end iterator when no protocol features have been activated"
652 );
653 _index = _pfm->_activated_protocol_features.size() - 1;
654 } else {
655 SYS_ASSERT( _index > 0,
656 protocol_feature_iterator_exception,
657 "cannot decrement iterator at the beginning of protocol feature activation list" )
658 ;
659 --_index;
660 }
661 return *this;
662 }
663
665 if( _activated_protocol_features.size() == 0 ) {
666 return cend();
667 } else {
668 return const_iterator( this, 0 );
669 }
670 }
671
674 if( activation_ordinal >= _activated_protocol_features.size() ) {
675 return cend();
676 }
677
678 return const_iterator{this, static_cast<std::size_t>(activation_ordinal)};
679 }
680
683 const auto begin = _activated_protocol_features.cbegin();
684 const auto end = _activated_protocol_features.cend();
685 auto itr = std::lower_bound( begin, end, block_num, []( const protocol_feature_entry& lhs, uint32_t rhs ) {
686 return lhs.activation_block_num < rhs;
687 } );
688
689 if( itr == end ) {
690 return cend();
691 }
692
693 return const_iterator{this, static_cast<std::size_t>(itr - begin)};
694 }
695
698 const auto begin = _activated_protocol_features.cbegin();
699 const auto end = _activated_protocol_features.cend();
700 auto itr = std::upper_bound( begin, end, block_num, []( uint32_t lhs, const protocol_feature_entry& rhs ) {
701 return lhs < rhs.activation_block_num;
702 } );
703
704 if( itr == end ) {
705 return cend();
706 }
707
708 return const_iterator{this, static_cast<std::size_t>(itr - begin)};
709 }
710
712 uint32_t current_block_num )const
713 {
714 uint32_t indx = static_cast<uint32_t>( feature_codename );
715
716 if( indx >= _builtin_protocol_features.size() ) return false;
717
718 return (_builtin_protocol_features[indx].activation_block_num <= current_block_num);
719 }
720
722 uint32_t current_block_num )
723 {
724 SYS_ASSERT( is_initialized(), protocol_feature_exception, "protocol_feature_manager is not yet initialized" );
725
726 auto itr = _protocol_feature_set.find( feature_digest );
727
728 SYS_ASSERT( itr != _protocol_feature_set.end(), protocol_feature_exception,
729 "unrecognized protocol feature digest: ${digest}", ("digest", feature_digest) );
730
731 if( _activated_protocol_features.size() > 0 ) {
732 const auto& last = _activated_protocol_features.back();
733 SYS_ASSERT( last.activation_block_num <= current_block_num,
734 protocol_feature_exception,
735 "last protocol feature activation block num is ${last_activation_block_num} yet "
736 "attempting to activate protocol feature with a current block num of ${current_block_num}"
737 "protocol features is ${last_activation_block_num}",
738 ("current_block_num", current_block_num)
739 ("last_activation_block_num", last.activation_block_num)
740 );
741 }
742
743 SYS_ASSERT( itr->builtin_feature,
744 protocol_feature_exception,
745 "invariant failure: encountered non-builtin protocol feature which is not yet supported"
746 );
747
748 uint32_t indx = static_cast<uint32_t>( *itr->builtin_feature );
749
750 SYS_ASSERT( indx < _builtin_protocol_features.size(), protocol_feature_exception,
751 "invariant failure while trying to activate feature with digest '${digest}': "
752 "unsupported builtin_protocol_feature_t ${codename}",
753 ("digest", feature_digest)
754 ("codename", indx)
755 );
756
758 protocol_feature_exception,
759 "cannot activate already activated builtin feature with digest: ${digest}",
760 ("digest", feature_digest)
761 );
762
763 if (auto dm_logger = _get_deep_mind_logger()) {
764 dm_logger->on_activate_feature(*itr);
765 }
766
767 _activated_protocol_features.push_back( protocol_feature_entry{itr, current_block_num} );
769 _builtin_protocol_features[indx].activation_block_num = current_block_num;
771 }
772
774 SYS_ASSERT( is_initialized(), protocol_feature_exception, "protocol_feature_manager is not yet initialized" );
775
778 if( e.activation_block_num <= block_num ) break;
779
782 e.activation_block_num = builtin_protocol_feature_entry::not_active;
783 }
784
785 while( _activated_protocol_features.size() > 0
786 && block_num < _activated_protocol_features.back().activation_block_num )
787 {
789 }
790 }
791
792} } // sysio::chain
const mie::Vuint & p
Definition bn.cpp:27
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
const ObjectType & get(CompatibleKey &&key) const
An order-preserving dictionary of variants.
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
T as() const
Definition variant.hpp:327
const_iterator at_activation_ordinal(uint32_t activation_ordinal) const
vector< builtin_protocol_feature_entry > _builtin_protocol_features
vector< protocol_feature_entry > _activated_protocol_features
void activate_feature(const digest_type &feature_digest, uint32_t current_block_num)
bool is_builtin_activated(builtin_protocol_feature_t feature_codename, uint32_t current_block_num) const
protocol_feature_manager(protocol_feature_set &&pfs, std::function< deep_mind_handler *()> get_deep_mind_logger)
const_iterator upper_bound(uint32_t block_num) const
const_iterator lower_bound(uint32_t block_num) const
vector< protocol_feature_set_type::const_iterator > _recognized_builtin_protocol_features
static builtin_protocol_feature make_default_builtin_protocol_feature(builtin_protocol_feature_t codename, const std::function< digest_type(builtin_protocol_feature_t dependency)> &handle_dependency)
std::optional< digest_type > get_builtin_digest(builtin_protocol_feature_t feature_codename) const
recognized_t is_recognized(const digest_type &feature_digest, time_point now) const
const_iterator find(const K &x) const
bool validate_dependencies(const digest_type &feature_digest, const std::function< bool(const digest_type &)> &validator) const
const protocol_feature & add_feature(const builtin_protocol_feature &f)
const protocol_feature & get_protocol_feature(const digest_type &feature_digest) const
protocol_feature_set_type _recognized_protocol_features
Maintains global state information about consensus protocol rules.
shared_vector< activated_protocol_feature > activated_protocol_features
constexpr bool has_feature_reflector_init_on_unpacked_reflected_types
Definition raw.hpp:440
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
scoped_exit< Callback > make_scoped_exit(Callback &&c)
std::vector< fc::variant > variants
Definition variant.hpp:173
Definition name.hpp:106
const std::unordered_map< builtin_protocol_feature_t, builtin_protocol_feature_spec, enum_hash< builtin_protocol_feature_t > > builtin_protocol_feature_codenames
end_insert_iterator< Container > end_inserter(Container &c)
Definition types.hpp:303
checksum_type digest_type
Definition types.hpp:237
const char * builtin_protocol_feature_codename(builtin_protocol_feature_t)
#define value
Definition pkcs11.h:157
unsigned int uint32_t
Definition stdint.h:126
static constexpr size_t no_previous
static constexpr uint32_t not_active
uint32_t activation_block_num
std::optional< builtin_protocol_feature_t > builtin_feature
fc::variant to_variant(bool include_subjective_restrictions=true, fc::mutable_variant_object *additional_fields=nullptr) const
CK_ULONG d