Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
block_header_state.cpp
Go to the documentation of this file.
3#include <limits>
4
5namespace sysio { namespace chain {
6
7 namespace detail {
9 const protocol_feature_set& pfs,
10 builtin_protocol_feature_t feature_codename )
11 {
12 auto digest = pfs.get_builtin_digest(feature_codename);
13 const auto& protocol_features = pfa->protocol_features;
14 return digest && protocol_features.find(*digest) != protocol_features.end();
15 }
16 }
17
19 auto index = t.slot % (active_schedule.producers.size() * config::producer_repetitions);
20 index /= config::producer_repetitions;
21 return active_schedule.producers[index];
22 }
23
25 vector<uint32_t> blocknums; blocknums.reserve( producer_to_last_implied_irb.size() );
26 for( auto& i : producer_to_last_implied_irb ) {
27 blocknums.push_back( (i.first == producer_of_next_block) ? dpos_proposed_irreversible_blocknum : i.second);
28 }
30
31 if( blocknums.size() == 0 ) return 0;
32
33 std::size_t index = (blocknums.size()-1) / 3;
34 std::nth_element( blocknums.begin(), blocknums.begin() + index, blocknums.end() );
35 return blocknums[ index ];
36 }
37
39 uint16_t num_prev_blocks_to_confirm )const
40 {
42
43 if( when != block_timestamp_type() ) {
44 SYS_ASSERT( when > header.timestamp, block_validate_exception, "next block must be in the future" );
45 } else {
46 (when = header.timestamp).slot++;
47 }
48
49 auto proauth = get_scheduled_producer(when);
50
51 auto itr = producer_to_last_produced.find( proauth.producer_name );
52 if( itr != producer_to_last_produced.end() ) {
53 SYS_ASSERT( itr->second < (block_num+1) - num_prev_blocks_to_confirm, producer_double_confirm,
54 "producer ${prod} double-confirming known range",
55 ("prod", proauth.producer_name)("num", block_num+1)
56 ("confirmed", num_prev_blocks_to_confirm)("last_produced", itr->second) );
57 }
58
59 result.block_num = block_num + 1;
60 result.previous = id;
61 result.timestamp = when;
62 result.confirmed = num_prev_blocks_to_confirm;
63 result.active_schedule_version = active_schedule.version;
64 result.prev_activated_protocol_features = activated_protocol_features;
65
66 result.valid_block_signing_authority = proauth.authority;
67 result.producer = proauth.producer_name;
68
69 result.blockroot_merkle = blockroot_merkle;
70 result.blockroot_merkle.append( id );
71
73 static_assert(std::numeric_limits<uint8_t>::max() >= (config::max_producers * 2 / 3) + 1, "8bit confirmations may not be able to hold all of the needed confirmations");
74
75 // This uses the previous block active_schedule because thats the "schedule" that signs and therefore confirms _this_ block
76 auto num_active_producers = active_schedule.producers.size();
77 uint32_t required_confs = (uint32_t)(num_active_producers * 2 / 3) + 1;
78
79 if( confirm_count.size() < config::maximum_tracked_dpos_confirmations ) {
80 result.confirm_count.reserve( confirm_count.size() + 1 );
81 result.confirm_count = confirm_count;
82 result.confirm_count.resize( confirm_count.size() + 1 );
83 result.confirm_count.back() = (uint8_t)required_confs;
84 } else {
85 result.confirm_count.resize( confirm_count.size() );
86 memcpy( &result.confirm_count[0], &confirm_count[1], confirm_count.size() - 1 );
87 result.confirm_count.back() = (uint8_t)required_confs;
88 }
89
90 auto new_dpos_proposed_irreversible_blocknum = dpos_proposed_irreversible_blocknum;
91
92 int32_t i = (int32_t)(result.confirm_count.size() - 1);
93 uint32_t blocks_to_confirm = num_prev_blocks_to_confirm + 1;
94 while( i >= 0 && blocks_to_confirm ) {
95 --result.confirm_count[i];
96 //idump((confirm_count[i]));
97 if( result.confirm_count[i] == 0 )
98 {
99 uint32_t block_num_for_i = result.block_num - (uint32_t)(result.confirm_count.size() - 1 - i);
100 new_dpos_proposed_irreversible_blocknum = block_num_for_i;
101 //idump((dpos2_lib)(block_num)(dpos_irreversible_blocknum));
102
103 if (i == static_cast<int32_t>(result.confirm_count.size() - 1)) {
104 result.confirm_count.resize(0);
105 } else {
106 memmove( &result.confirm_count[0], &result.confirm_count[i + 1], result.confirm_count.size() - i - 1);
107 result.confirm_count.resize( result.confirm_count.size() - i - 1 );
108 }
109
110 break;
111 }
112 --i;
113 --blocks_to_confirm;
114 }
115
116 result.dpos_proposed_irreversible_blocknum = new_dpos_proposed_irreversible_blocknum;
117 result.dpos_irreversible_blocknum = calc_dpos_last_irreversible( proauth.producer_name );
118
119 result.prev_pending_schedule = pending_schedule;
120
122 result.dpos_irreversible_blocknum >= pending_schedule.schedule_lib_num )
123 {
124 result.active_schedule = pending_schedule.schedule;
125
126 flat_map<account_name,uint32_t> new_producer_to_last_produced;
127
128 for( const auto& pro : result.active_schedule.producers ) {
129 if( pro.producer_name == proauth.producer_name ) {
130 new_producer_to_last_produced[pro.producer_name] = result.block_num;
131 } else {
132 auto existing = producer_to_last_produced.find( pro.producer_name );
133 if( existing != producer_to_last_produced.end() ) {
134 new_producer_to_last_produced[pro.producer_name] = existing->second;
135 } else {
136 new_producer_to_last_produced[pro.producer_name] = result.dpos_irreversible_blocknum;
137 }
138 }
139 }
140 new_producer_to_last_produced[proauth.producer_name] = result.block_num;
141
142 result.producer_to_last_produced = std::move( new_producer_to_last_produced );
143
144 flat_map<account_name,uint32_t> new_producer_to_last_implied_irb;
145
146 for( const auto& pro : result.active_schedule.producers ) {
147 if( pro.producer_name == proauth.producer_name ) {
148 new_producer_to_last_implied_irb[pro.producer_name] = dpos_proposed_irreversible_blocknum;
149 } else {
150 auto existing = producer_to_last_implied_irb.find( pro.producer_name );
151 if( existing != producer_to_last_implied_irb.end() ) {
152 new_producer_to_last_implied_irb[pro.producer_name] = existing->second;
153 } else {
154 new_producer_to_last_implied_irb[pro.producer_name] = result.dpos_irreversible_blocknum;
155 }
156 }
157 }
158
159 result.producer_to_last_implied_irb = std::move( new_producer_to_last_implied_irb );
160
161 result.was_pending_promoted = true;
162 } else {
163 result.active_schedule = active_schedule;
164 result.producer_to_last_produced = producer_to_last_produced;
165 result.producer_to_last_produced[proauth.producer_name] = result.block_num;
166 result.producer_to_last_implied_irb = producer_to_last_implied_irb;
167 result.producer_to_last_implied_irb[proauth.producer_name] = dpos_proposed_irreversible_blocknum;
168 }
169
170 return result;
171 }
172
174 const checksum256_type& transaction_mroot,
175 const checksum256_type& action_mroot,
176 const std::optional<producer_authority_schedule>& new_producers,
177 vector<digest_type>&& new_protocol_feature_activations,
178 const protocol_feature_set& pfs,
179 const std::optional<s_header>& s_header
180 )const
181 {
183
185 h.producer = producer;
187 h.previous = previous;
188 h.transaction_mroot = transaction_mroot;
189 h.action_mroot = action_mroot;
191
192 if( new_protocol_feature_activations.size() > 0 ) {
196 fc::raw::pack( protocol_feature_activation{ std::move(new_protocol_feature_activations) } )
197 );
198 }
199
200 if (new_producers) {
202 // add the header extension to update the block schedule
207 );
208 } else {
209 legacy::producer_schedule_type downgraded_producers;
210 downgraded_producers.version = new_producers->version;
211 for (const auto &p : new_producers->producers) {
212 std::visit([&downgraded_producers, &p](const auto& auth)
213 {
214 SYS_ASSERT(auth.keys.size() == 1 && auth.keys.front().weight == auth.threshold, producer_schedule_exception, "multisig block signing present before enabled!");
215 downgraded_producers.producers.emplace_back(legacy::producer_key{p.producer_name, auth.keys.front().key});
216 }, p.authority);
217 }
218 h.new_producers = std::move(downgraded_producers);
219 }
220 }
221
222 // Add s_root_extension to header extensions if present & relevant
223 if (s_header) {
228 );
229 }
230
231 return h;
232 }
233
235 const signed_block_header& h,
236 const protocol_feature_set& pfs,
237 const std::function<void( block_timestamp_type,
238 const flat_set<digest_type>&,
239 const vector<digest_type>& )>& validator
240
241 )&&
242 {
243 SYS_ASSERT( h.timestamp == timestamp, block_validate_exception, "timestamp mismatch" );
244 SYS_ASSERT( h.previous == previous, unlinkable_block_exception, "previous mismatch" );
245 SYS_ASSERT( h.confirmed == confirmed, block_validate_exception, "confirmed mismatch" );
246 SYS_ASSERT( h.producer == producer, wrong_producer, "wrong producer specified" );
247 SYS_ASSERT( h.schedule_version == active_schedule_version, producer_schedule_exception, "schedule_version in signed block is corrupted" );
248
250
251 std::optional<producer_authority_schedule> maybe_new_producer_schedule;
252 std::optional<digest_type> maybe_new_producer_schedule_hash;
253 bool wtmsig_enabled = false;
254
256 wtmsig_enabled = detail::is_builtin_activated(prev_activated_protocol_features, pfs, builtin_protocol_feature_t::wtmsig_block_signatures);
257 }
258
259 if( h.new_producers ) {
260 SYS_ASSERT(!wtmsig_enabled, producer_schedule_exception, "Block header contains legacy producer schedule outdated by activation of WTMsig Block Signatures" );
261
262 SYS_ASSERT( !was_pending_promoted, producer_schedule_exception, "cannot set pending producer schedule in the same block in which pending was promoted to active" );
263
264 const auto& new_producers = *h.new_producers;
265 SYS_ASSERT( new_producers.version == active_schedule.version + 1, producer_schedule_exception, "wrong producer schedule version specified" );
266 SYS_ASSERT( prev_pending_schedule.schedule.producers.empty(), producer_schedule_exception,
267 "cannot set new pending producers until last pending is confirmed" );
268
269 maybe_new_producer_schedule_hash.emplace(digest_type::hash(new_producers));
270 maybe_new_producer_schedule.emplace(new_producers);
271 }
272
273 if ( exts.count(producer_schedule_change_extension::extension_id()) > 0 ) {
274 SYS_ASSERT(wtmsig_enabled, producer_schedule_exception, "Block header producer_schedule_change_extension before activation of WTMsig Block Signatures" );
275 SYS_ASSERT( !was_pending_promoted, producer_schedule_exception, "cannot set pending producer schedule in the same block in which pending was promoted to active" );
276
277 const auto& new_producer_schedule = std::get<producer_schedule_change_extension>(exts.lower_bound(producer_schedule_change_extension::extension_id())->second);
278
279 SYS_ASSERT( new_producer_schedule.version == active_schedule.version + 1, producer_schedule_exception, "wrong producer schedule version specified" );
280 SYS_ASSERT( prev_pending_schedule.schedule.producers.empty(), producer_schedule_exception,
281 "cannot set new pending producers until last pending is confirmed" );
282
283 maybe_new_producer_schedule_hash.emplace(digest_type::hash(new_producer_schedule));
284 maybe_new_producer_schedule.emplace(new_producer_schedule);
285 }
286
287 protocol_feature_activation_set_ptr new_activated_protocol_features;
288 { // handle protocol_feature_activation
289 if( exts.count(protocol_feature_activation::extension_id() > 0) ) {
290 const auto& new_protocol_features = std::get<protocol_feature_activation>(exts.lower_bound(protocol_feature_activation::extension_id())->second).protocol_features;
291 validator( timestamp, prev_activated_protocol_features->protocol_features, new_protocol_features );
292
293 new_activated_protocol_features = std::make_shared<protocol_feature_activation_set>(
294 *prev_activated_protocol_features,
295 new_protocol_features
296 );
297 } else {
298 new_activated_protocol_features = std::move( prev_activated_protocol_features );
299 }
300 }
301
302 auto block_number = block_num;
303
304 block_header_state result( std::move( *static_cast<detail::block_header_state_common*>(this) ) );
305
306 result.id = h.calculate_id();
307 result.header = h;
308
309 result.header_exts = std::move(exts);
310
311 if( maybe_new_producer_schedule ) {
312 result.pending_schedule.schedule = std::move(*maybe_new_producer_schedule);
313 result.pending_schedule.schedule_hash = std::move(*maybe_new_producer_schedule_hash);
314 result.pending_schedule.schedule_lib_num = block_number;
315 } else {
316 if( was_pending_promoted ) {
317 result.pending_schedule.schedule.version = prev_pending_schedule.schedule.version;
318 } else {
319 result.pending_schedule.schedule = std::move( prev_pending_schedule.schedule );
320 }
321 result.pending_schedule.schedule_hash = std::move( prev_pending_schedule.schedule_hash );
322 result.pending_schedule.schedule_lib_num = prev_pending_schedule.schedule_lib_num;
323 }
324
325 result.activated_protocol_features = std::move( new_activated_protocol_features );
326
327 return result;
328 }
329
331 const signed_block_header& h,
332 vector<signature_type>&& additional_signatures,
333 const protocol_feature_set& pfs,
334 const std::function<void( block_timestamp_type,
335 const flat_set<digest_type>&,
336 const vector<digest_type>& )>& validator,
337 bool skip_validate_signee
338 )&&
339 {
340 if( !additional_signatures.empty() ) {
341 bool wtmsig_enabled = detail::is_builtin_activated(prev_activated_protocol_features, pfs, builtin_protocol_feature_t::wtmsig_block_signatures);
342
343 SYS_ASSERT(wtmsig_enabled, producer_schedule_exception, "Block contains multiple signatures before WTMsig block signatures are enabled" );
344 }
345
346 auto result = std::move(*this)._finish_next( h, pfs, validator );
347
348 if( !additional_signatures.empty() ) {
349 result.additional_signatures = std::move(additional_signatures);
350 }
351
352 // ASSUMPTION FROM controller_impl::apply_block = all untrusted blocks will have their signatures pre-validated here
353 if( !skip_validate_signee ) {
354 result.verify_signee( );
355 }
356
357 return result;
358 }
359
362 const protocol_feature_set& pfs,
363 const std::function<void( block_timestamp_type,
364 const flat_set<digest_type>&,
365 const vector<digest_type>& )>& validator,
366 const signer_callback_type& signer
367 )&&
368 {
369 auto pfa = prev_activated_protocol_features;
370
371 auto result = std::move(*this)._finish_next( h, pfs, validator );
372 result.sign( signer );
373 h.producer_signature = result.header.producer_signature;
374
375 if( !result.additional_signatures.empty() ) {
377 SYS_ASSERT(wtmsig_enabled, producer_schedule_exception, "Block was signed with multiple signatures before WTMsig block signatures are enabled" );
378 }
379
380 return result;
381 }
382
392 const signed_block_header& h,
393 vector<signature_type>&& _additional_signatures,
394 const protocol_feature_set& pfs,
395 const std::function<void( block_timestamp_type,
396 const flat_set<digest_type>&,
397 const vector<digest_type>& )>& validator,
398 bool skip_validate_signee )const
399 {
400 return next( h.timestamp, h.confirmed ).finish_next( h, std::move(_additional_signatures), pfs, validator, skip_validate_signee );
401 }
402
404 auto header_bmroot = digest_type::hash( std::make_pair( header.digest(), blockroot_merkle.get_root() ) );
405 return digest_type::hash( std::make_pair(header_bmroot, pending_schedule.schedule_hash) );
406 }
407
409 auto d = sig_digest();
410 auto sigs = signer( d );
411
412 SYS_ASSERT(!sigs.empty(), no_block_signatures, "Signer returned no signatures");
413 header.producer_signature = sigs.back();
414 sigs.pop_back();
415
416 additional_signatures = std::move(sigs);
417
419 }
420
422
423 auto num_keys_in_authority = std::visit([](const auto &a){ return a.keys.size(); }, valid_block_signing_authority);
424 SYS_ASSERT(1 + additional_signatures.size() <= num_keys_in_authority, wrong_signing_key,
425 "number of block signatures (${num_block_signatures}) exceeds number of keys in block signing authority (${num_keys})",
426 ("num_block_signatures", 1 + additional_signatures.size())
427 ("num_keys", num_keys_in_authority)
428 ("authority", valid_block_signing_authority)
429 );
430
431 std::set<public_key_type> keys;
432 auto digest = sig_digest();
434
435 for (const auto& s: additional_signatures) {
436 auto res = keys.emplace(s, digest, true);
437 SYS_ASSERT(res.second, wrong_signing_key, "block signed by same key twice", ("key", *res.first));
438 }
439
440 bool is_satisfied = false;
441 size_t relevant_sig_count = 0;
442
443 std::tie(is_satisfied, relevant_sig_count) = producer_authority::keys_satisfy_and_relevant(keys, valid_block_signing_authority);
444
445 SYS_ASSERT(relevant_sig_count == keys.size(), wrong_signing_key,
446 "block signed by unexpected key",
447 ("signing_keys", keys)("authority", valid_block_signing_authority));
448
449 SYS_ASSERT(is_satisfied, wrong_signing_key,
450 "block signatures do not satisfy the block signing authority",
451 ("signing_keys", keys)("authority", valid_block_signing_authority));
452 }
453
458 static const vector<digest_type> no_activations{};
459
461 return no_activations;
462
463 return std::get<protocol_feature_activation>(header_exts.lower_bound(protocol_feature_activation::extension_id())->second).protocol_features;
464 }
465
467 {
468 block_num = snapshot.block_num;
469 dpos_proposed_irreversible_blocknum = snapshot.dpos_proposed_irreversible_blocknum;
470 dpos_irreversible_blocknum = snapshot.dpos_irreversible_blocknum;
471 active_schedule = producer_authority_schedule( snapshot.active_schedule );
472 blockroot_merkle = std::move(snapshot.blockroot_merkle);
473 producer_to_last_produced = std::move(snapshot.producer_to_last_produced);
474 producer_to_last_implied_irb = std::move(snapshot.producer_to_last_implied_irb);
475 valid_block_signing_authority = block_signing_authority_v0{ 1, {{std::move(snapshot.block_signing_key), 1}} };
476 confirm_count = std::move(snapshot.confirm_count);
477 id = std::move(snapshot.id);
478 header = std::move(snapshot.header);
479 pending_schedule.schedule_lib_num = snapshot.pending_schedule.schedule_lib_num;
480 pending_schedule.schedule_hash = std::move(snapshot.pending_schedule.schedule_hash);
481 pending_schedule.schedule = producer_authority_schedule( snapshot.pending_schedule.schedule );
482 activated_protocol_features = std::move(snapshot.activated_protocol_features);
483 }
484
485
486} }
const mie::Vuint & p
Definition bn.cpp:27
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
static sha256 hash(const char *d, uint32_t dlen)
Definition sha256.cpp:44
std::optional< digest_type > get_builtin_digest(builtin_protocol_feature_t feature_codename) const
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
fc::sha256 digest(const T &value)
Definition digest.hpp:9
bool is_builtin_activated(const protocol_feature_activation_set_ptr &pfa, const protocol_feature_set &pfs, builtin_protocol_feature_t feature_codename)
block_timestamp< config::block_interval_ms, config::block_timestamp_epoch > block_timestamp_type
std::function< std::vector< signature_type >(const digest_type &)> signer_callback_type
auto emplace_extension(extensions_type &exts, uint16_t eid, vector< char > &&data)
Definition types.hpp:264
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 block_validate_exception
std::shared_ptr< protocol_feature_activation_set > protocol_feature_activation_set_ptr
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
unsigned short uint16_t
Definition stdint.h:125
unsigned int uint32_t
Definition stdint.h:126
signed int int32_t
Definition stdint.h:123
unsigned char uint8_t
Definition stdint.h:124
defines the minimum state necessary to validate transaction headers
protocol_feature_activation_set_ptr activated_protocol_features
flat_multimap< uint16_t, block_header_extension > header_exts
pending_block_header_state next(block_timestamp_type when, uint16_t num_prev_blocks_to_confirm) const
producer_authority get_scheduled_producer(block_timestamp_type t) const
uint32_t calc_dpos_last_irreversible(account_name producer_of_next_block) const
vector< signature_type > additional_signatures
const vector< digest_type > & get_new_protocol_feature_activations() const
void sign(const signer_callback_type &signer)
block_timestamp_type timestamp
checksum256_type transaction_mroot
checksum256_type action_mroot
mroot of cycles_summary
digest_type digest() const
extensions_type header_extensions
block_id_type calculate_id() const
flat_multimap< uint16_t, block_header_extension > validate_and_extract_header_extensions() const
new_producers_type new_producers
flat_map< account_name, uint32_t > producer_to_last_implied_irb
flat_map< account_name, uint32_t > producer_to_last_produced
producer_authority_schedule schedule
digest_type schedule_hash
last irr block num
uint32_t version
sequentially incrementing version number
Immutable except for fc::from_variant.
Definition name.hpp:43
block_header_state finish_next(const signed_block_header &h, vector< signature_type > &&additional_signatures, const protocol_feature_set &pfs, const std::function< void(block_timestamp_type, const flat_set< digest_type > &, const vector< digest_type > &)> &validator, bool skip_validate_signee=false) &&
signed_block_header make_block_header(const checksum256_type &transaction_mroot, const checksum256_type &action_mroot, const std::optional< producer_authority_schedule > &new_producers, vector< digest_type > &&new_protocol_feature_activations, const protocol_feature_set &pfs, const std::optional< s_header > &s_header) const
block_header_state _finish_next(const signed_block_header &h, const protocol_feature_set &pfs, const std::function< void(block_timestamp_type, const flat_set< digest_type > &, const vector< digest_type > &)> &validator) &&
protocol_feature_activation_set_ptr prev_activated_protocol_features
uint32_t version
sequentially incrementing version number
static std::pair< bool, size_t > keys_satisfy_and_relevant(const std::set< public_key_type > &keys, const block_signing_authority &authority)
static constexpr uint16_t extension_id()
yubihsm_pkcs11_slot * slot
CK_ULONG d
char * s
memcpy((char *) pInfo->slotDescription, s, l)