BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
db_block.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
27 #include <graphene/chain/hardfork.hpp>
28 
32 
39 
41 
42 #include <fc/io/raw.hpp>
43 #include <fc/thread/parallel.hpp>
44 
45 namespace graphene { namespace chain {
46 
48 {
49  return _fork_db.is_known_block(id) || _block_id_to_block.contains(id);
50 }
57 {
58  const auto& trx_idx = get_index_type<transaction_index>().indices().get<by_trx_id>();
59  return trx_idx.find( id ) != trx_idx.end();
60 }
61 
63 { try {
64  return _block_id_to_block.fetch_block_id( block_num );
65 } FC_CAPTURE_AND_RETHROW( (block_num) ) }
66 
68 {
69  auto b = _fork_db.fetch_block( id );
70  if( !b )
71  return _block_id_to_block.fetch_optional(id);
72  return b->data;
73 }
74 
76 {
77  auto results = _fork_db.fetch_block_by_number(num);
78  if( results.size() == 1 )
79  return results[0]->data;
80  else
81  return _block_id_to_block.fetch_by_number(num);
82 }
83 
85 {
86  auto& index = get_index_type<transaction_index>().indices().get<by_trx_id>();
87  auto itr = index.find(trx_id);
88  FC_ASSERT(itr != index.end());
89  return itr->trx;
90 }
91 
92 std::vector<block_id_type> database::get_block_ids_on_fork(block_id_type head_of_fork) const
93 {
94  pair<fork_database::branch_type, fork_database::branch_type> branches = _fork_db.fetch_branch_from(head_block_id(), head_of_fork);
95  if( !((branches.first.back()->previous_id() == branches.second.back()->previous_id())) )
96  {
97  edump( (head_of_fork)
98  (head_block_id())
99  (branches.first.size())
100  (branches.second.size()) );
101  assert(branches.first.back()->previous_id() == branches.second.back()->previous_id());
102  }
103  std::vector<block_id_type> result;
104  for (const item_ptr& fork_block : branches.second)
105  result.emplace_back(fork_block->id);
106  result.emplace_back(branches.first.back()->previous_id());
107  return result;
108 }
109 
116 bool database::push_block(const signed_block& new_block, uint32_t skip)
117 {
118 // idump((new_block.block_num())(new_block.id())(new_block.timestamp)(new_block.previous));
119  bool result;
120  detail::with_skip_flags( *this, skip, [&]()
121  {
122  detail::without_pending_transactions( *this, std::move(_pending_tx),
123  [&]()
124  {
125  result = _push_block(new_block);
126  });
127  });
128  return result;
129 }
130 
131 bool database::_push_block(const signed_block& new_block)
132 { try {
133  uint32_t skip = get_node_properties().skip_flags;
134 
135  const auto now = fc::time_point::now().sec_since_epoch();
136  if( _fork_db.head() && new_block.timestamp.sec_since_epoch() > now - 86400 )
137  {
138  // verify that the block signer is in the current set of active witnesses.
139  shared_ptr<fork_item> prev_block = _fork_db.fetch_block( new_block.previous );
140  GRAPHENE_ASSERT( prev_block, unlinkable_block_exception, "block does not link to known chain" );
141  if( prev_block->scheduled_witnesses && !(skip&(skip_witness_schedule_check|skip_witness_signature)) )
142  verify_signing_witness( new_block, *prev_block );
143  }
144 
145  const shared_ptr<fork_item> new_head = _fork_db.push_block(new_block);
146  //If the head block from the longest chain does not build off of the current head, we need to switch forks.
147  if( new_head->data.previous != head_block_id() )
148  {
149  //If the newly pushed block is the same height as head, we get head back in new_head
150  //Only switch forks if new_head is actually higher than head
151  if( new_head->data.block_num() > head_block_num() )
152  {
153  wlog( "Switching to fork: ${id}", ("id",new_head->data.id()) );
154  auto branches = _fork_db.fetch_branch_from(new_head->data.id(), head_block_id());
155 
156  // pop blocks until we hit the forked block
157  while( head_block_id() != branches.second.back()->data.previous )
158  {
159  ilog( "popping block #${n} ${id}", ("n",head_block_num())("id",head_block_id()) );
160  pop_block();
161  }
162 
163  // push all blocks on the new fork
164  for( auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr )
165  {
166  ilog( "pushing block from fork #${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->id) );
168  try {
170  apply_block( (*ritr)->data, skip );
171  update_witnesses( **ritr );
172  _block_id_to_block.store( (*ritr)->id, (*ritr)->data );
173  session.commit();
174  }
175  catch ( const fc::exception& e ) { except = e; }
176  if( except )
177  {
178  wlog( "exception thrown while switching forks ${e}", ("e",except->to_detail_string() ) );
179  // remove the rest of branches.first from the fork_db, those blocks are invalid
180  while( ritr != branches.first.rend() )
181  {
182  ilog( "removing block from fork_db #${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->id) );
183  _fork_db.remove( (*ritr)->id );
184  ++ritr;
185  }
186  _fork_db.set_head( branches.second.front() );
187 
188  // pop all blocks from the bad fork
189  while( head_block_id() != branches.second.back()->data.previous )
190  {
191  ilog( "popping block #${n} ${id}", ("n",head_block_num())("id",head_block_id()) );
192  pop_block();
193  }
194 
195  ilog( "Switching back to fork: ${id}", ("id",branches.second.front()->data.id()) );
196  // restore all blocks from the good fork
197  for( auto ritr2 = branches.second.rbegin(); ritr2 != branches.second.rend(); ++ritr2 )
198  {
199  ilog( "pushing block #${n} ${id}", ("n",(*ritr2)->data.block_num())("id",(*ritr2)->id) );
200  auto session = _undo_db.start_undo_session();
201  apply_block( (*ritr2)->data, skip );
202  _block_id_to_block.store( (*ritr2)->id, (*ritr2)->data );
203  session.commit();
204  }
205  throw *except;
206  }
207  }
208  return true;
209  }
210  else return false;
211  }
212 
213  try {
214  auto session = _undo_db.start_undo_session();
215  apply_block(new_block, skip);
216  if( new_block.timestamp.sec_since_epoch() > now - 86400 )
217  update_witnesses( *new_head );
218  _block_id_to_block.store(new_block.id(), new_block);
219  session.commit();
220  } catch ( const fc::exception& e ) {
221  elog("Failed to push new block:\n${e}", ("e", e.to_detail_string()));
222  _fork_db.remove( new_block.id() );
223  throw;
224  }
225 
226  return false;
227 } FC_CAPTURE_AND_RETHROW( (new_block) ) }
228 
229 void database::verify_signing_witness( const signed_block& new_block, const fork_item& fork_entry )const
230 {
231  FC_ASSERT( new_block.timestamp >= fork_entry.next_block_time );
232  uint32_t slot_num = ( new_block.timestamp - fork_entry.next_block_time ).to_seconds() / block_interval();
233  uint64_t index = ( fork_entry.next_block_aslot + slot_num ) % fork_entry.scheduled_witnesses->size();
234  const auto& scheduled_witness = (*fork_entry.scheduled_witnesses)[index];
235  FC_ASSERT( new_block.witness == scheduled_witness.first, "Witness produced block at wrong time",
236  ("block witness",new_block.witness)("scheduled",scheduled_witness)("slot_num",slot_num) );
237  FC_ASSERT( new_block.validate_signee( scheduled_witness.second ) );
238 }
239 
240 void database::update_witnesses( fork_item& fork_entry )const
241 {
242  if( fork_entry.scheduled_witnesses ) return;
243 
245  fork_entry.next_block_aslot = dpo.current_aslot + 1;
246  fork_entry.next_block_time = get_slot_time( 1 );
247 
249  fork_entry.scheduled_witnesses = std::make_shared< vector< pair< witness_id_type, public_key_type > > >();
250  fork_entry.scheduled_witnesses->reserve( wso.current_shuffled_witnesses.size() );
251  for( size_t i = 0; i < wso.current_shuffled_witnesses.size(); ++i )
252  {
253  const auto& witness = wso.current_shuffled_witnesses[i](*this);
254  fork_entry.scheduled_witnesses->emplace_back( wso.current_shuffled_witnesses[i], witness.signing_key );
255  }
256 }
257 
268 { try {
269  // see https://github.com/bitshares/bitshares-core/issues/1573
270  FC_ASSERT( fc::raw::pack_size( trx ) < (1024 * 1024), "Transaction exceeds maximum transaction size." );
271  processed_transaction result;
272  detail::with_skip_flags( *this, skip, [&]()
273  {
274  result = _push_transaction( trx );
275  } );
276  return result;
277 } FC_CAPTURE_AND_RETHROW( (trx) ) }
278 
280 {
281  // If this is the first transaction pushed after applying a block, start a new undo session.
282  // This allows us to quickly rewind to the clean state of the head block, in case a new block arrives.
283  if( !_pending_tx_session.valid() )
284  _pending_tx_session = _undo_db.start_undo_session();
285 
286  // Create a temporary undo session as a child of _pending_tx_session.
287  // The temporary session will be discarded by the destructor if
288  // _apply_transaction fails. If we make it to merge(), we
289  // apply the changes.
290 
291  auto temp_session = _undo_db.start_undo_session();
292  auto processed_trx = _apply_transaction( trx );
293  _pending_tx.push_back(processed_trx);
294 
295  // notify_changed_objects();
296  // The transaction applied successfully. Merge its changes into the pending block session.
297  temp_session.merge();
298 
299  // notify anyone listening to pending transactions
301  return processed_trx;
302 }
303 
305 {
306  auto session = _undo_db.start_undo_session();
307  return _apply_transaction( trx );
308 }
309 
311 public:
312  push_proposal_nesting_guard( uint32_t& nesting_counter, const database& db )
313  : orig_value(nesting_counter), counter(nesting_counter)
314  {
315  FC_ASSERT( counter < db.get_global_properties().active_witnesses.size() * 2, "Max proposal nesting depth exceeded!" );
316  counter++;
317  }
319  {
320  if( --counter != orig_value )
321  elog( "Unexpected proposal nesting count value: ${n} != ${o}", ("n",counter)("o",orig_value) );
322  }
323 private:
324  const uint32_t orig_value;
325  uint32_t& counter;
326 };
327 
329 { try {
330  transaction_evaluation_state eval_state(this);
331  eval_state._is_proposed_trx = true;
332 
333  eval_state.operation_results.reserve(proposal.proposed_transaction.operations.size());
335  eval_state._trx = &ptrx;
336  size_t old_applied_ops_size = _applied_ops.size();
337 
338  try {
339  push_proposal_nesting_guard guard( _push_proposal_nesting_depth, *this );
340  if( _undo_db.size() >= _undo_db.max_size() )
342  auto session = _undo_db.start_undo_session(true);
343  for( auto& op : proposal.proposed_transaction.operations )
344  eval_state.operation_results.emplace_back(apply_operation(eval_state, op));
345  remove(proposal);
346  session.merge();
347  } catch ( const fc::exception& e ) {
348  if( head_block_time() <= HARDFORK_483_TIME )
349  {
350  for( size_t i=old_applied_ops_size,n=_applied_ops.size(); i<n; i++ )
351  {
352  ilog( "removing failed operation from applied_ops: ${op}", ("op", *(_applied_ops[i])) );
353  _applied_ops[i].reset();
354  }
355  }
356  else
357  {
358  _applied_ops.resize( old_applied_ops_size );
359  }
360  wlog( "${e}", ("e",e.to_detail_string() ) );
361  throw;
362  }
363 
364  ptrx.operation_results = std::move(eval_state.operation_results);
365  return ptrx;
366 } FC_CAPTURE_AND_RETHROW( (proposal) ) }
367 
369  fc::time_point_sec when,
370  witness_id_type witness_id,
371  const fc::ecc::private_key& block_signing_private_key,
372  uint32_t skip /* = 0 */
373  )
374 { try {
375  signed_block result;
376  detail::with_skip_flags( *this, skip, [&]()
377  {
378  result = _generate_block( when, witness_id, block_signing_private_key );
379  } );
380  return result;
382 
384  fc::time_point_sec when,
385  witness_id_type witness_id,
386  const fc::ecc::private_key& block_signing_private_key
387  )
388 {
389  try {
390  uint32_t skip = get_node_properties().skip_flags;
391  uint32_t slot_num = get_slot_at_time( when );
392  FC_ASSERT( slot_num > 0 );
393  witness_id_type scheduled_witness = get_scheduled_witness( slot_num );
394  FC_ASSERT( scheduled_witness == witness_id );
395 
396  //
397  // The following code throws away existing pending_tx_session and
398  // rebuilds it by re-applying pending transactions.
399  //
400  // This rebuild is necessary because pending transactions' validity
401  // and semantics may have changed since they were received, because
402  // time-based semantics are evaluated based on the current block
403  // time. These changes can only be reflected in the database when
404  // the value of the "when" variable is known, which means we need to
405  // re-apply pending transactions in this method.
406  //
407 
408  // pop pending state (reset to head block state)
409  _pending_tx_session.reset();
410 
411  // Check witness signing key
412  if( !(skip & skip_witness_signature) )
413  {
414  // Note: if this check failed (which won't happen in normal situations),
415  // we would have temporarily broken the invariant that
416  // _pending_tx_session is the result of applying _pending_tx.
417  // In this case, when the node received a new block,
418  // the push_block() call will re-create the _pending_tx_session.
419  FC_ASSERT( witness_id(*this).signing_key == block_signing_private_key.get_public_key() );
420  }
421 
422  static const size_t max_partial_block_header_size = fc::raw::pack_size( signed_block_header() )
423  - fc::raw::pack_size( witness_id_type() ) // witness_id
424  + 3; // max space to store size of transactions (out of block header),
425  // +3 means 3*7=21 bits so it's practically safe
426  const size_t max_block_header_size = max_partial_block_header_size + fc::raw::pack_size( witness_id );
427  auto maximum_block_size = get_global_properties().parameters.maximum_block_size;
428  size_t total_block_size = max_block_header_size;
429 
430  signed_block pending_block;
431 
432  _pending_tx_session = _undo_db.start_undo_session();
433 
434  uint64_t postponed_tx_count = 0;
435  for( const processed_transaction& tx : _pending_tx )
436  {
437  size_t new_total_size = total_block_size + fc::raw::pack_size( tx );
438 
439  // postpone transaction if it would make block too big
440  if( new_total_size > maximum_block_size )
441  {
442  postponed_tx_count++;
443  continue;
444  }
445 
446  try
447  {
448  auto temp_session = _undo_db.start_undo_session();
449  processed_transaction ptx = _apply_transaction( tx );
450 
451  // We have to recompute pack_size(ptx) because it may be different
452  // than pack_size(tx) (i.e. if one or more results increased
453  // their size)
454  new_total_size = total_block_size + fc::raw::pack_size( ptx );
455  // postpone transaction if it would make block too big
456  if( new_total_size > maximum_block_size )
457  {
458  postponed_tx_count++;
459  continue;
460  }
461 
462  temp_session.merge();
463 
464  total_block_size = new_total_size;
465  pending_block.transactions.push_back( ptx );
466  }
467  catch ( const fc::exception& e )
468  {
469  // Do nothing, transaction will not be re-applied
470  wlog( "Transaction was not processed while generating block due to ${e}", ("e", e) );
471  wlog( "The transaction was ${t}", ("t", tx) );
472  }
473  }
474  if( postponed_tx_count > 0 )
475  {
476  wlog( "Postponed ${n} transactions due to block size limit", ("n", postponed_tx_count) );
477  }
478 
479  _pending_tx_session.reset();
480 
481  // We have temporarily broken the invariant that
482  // _pending_tx_session is the result of applying _pending_tx, as
483  // _pending_tx now consists of the set of postponed transactions.
484  // However, the push_block() call below will re-create the
485  // _pending_tx_session.
486 
487  pending_block.previous = head_block_id();
488  pending_block.timestamp = when;
489  pending_block.transaction_merkle_root = pending_block.calculate_merkle_root();
490  pending_block.witness = witness_id;
491 
492  if( !(skip & skip_witness_signature) )
493  pending_block.sign( block_signing_private_key );
494 
495  push_block( pending_block, skip | skip_transaction_signatures ); // skip authority check when pushing self-generated blocks
496 
497  return pending_block;
498 } FC_CAPTURE_AND_RETHROW( (witness_id) ) }
499 
505 { try {
506  _pending_tx_session.reset();
507  auto fork_db_head = _fork_db.head();
508  FC_ASSERT( fork_db_head, "Trying to pop() from empty fork database!?" );
509  if( fork_db_head->id == head_block_id() )
510  _fork_db.pop_block();
511  else
512  {
513  fork_db_head = _fork_db.fetch_block( head_block_id() );
514  FC_ASSERT( fork_db_head, "Trying to pop() block that's not in fork database!?" );
515  }
516  pop_undo();
517  _popped_tx.insert( _popped_tx.begin(), fork_db_head->data.transactions.begin(), fork_db_head->data.transactions.end() );
519 
521 { try {
522  assert( (_pending_tx.size() == 0) || _pending_tx_session.valid() );
523  _pending_tx.clear();
524  _pending_tx_session.reset();
526 
528 {
529  _applied_ops.emplace_back(op);
530  operation_history_object& oh = *(_applied_ops.back());
531  oh.block_num = _current_block_num;
532  oh.trx_in_block = _current_trx_in_block;
533  oh.op_in_trx = _current_op_in_trx;
534  oh.virtual_op = _current_virtual_op++;
535  return _applied_ops.size() - 1;
536 }
537 void database::set_applied_operation_result( uint32_t op_id, const operation_result& result )
538 {
539  assert( op_id < _applied_ops.size() );
540  if( _applied_ops[op_id] )
541  _applied_ops[op_id]->result = result;
542  else
543  {
544  elog( "Could not set operation result (head_block_num=${b})", ("b", head_block_num()) );
545  }
546 }
547 
548 const vector<optional< operation_history_object > >& database::get_applied_operations() const
549 {
550  return _applied_ops;
551 }
552 
554 
555 void database::apply_block( const signed_block& next_block, uint32_t skip )
556 {
557  auto block_num = next_block.block_num();
558  if( _checkpoints.size() && _checkpoints.rbegin()->second != block_id_type() )
559  {
560  auto itr = _checkpoints.find( block_num );
561  if( itr != _checkpoints.end() )
562  FC_ASSERT( next_block.id() == itr->second, "Block did not match checkpoint", ("checkpoint",*itr)("block_id",next_block.id()) );
563 
564  if( _checkpoints.rbegin()->first >= block_num )
565  skip = ~0;// WE CAN SKIP ALMOST EVERYTHING
566  }
567 
568  detail::with_skip_flags( *this, skip, [&]()
569  {
570  _apply_block( next_block );
571  } );
572  return;
573 }
574 
575 void database::_apply_block( const signed_block& next_block )
576 { try {
577  uint32_t next_block_num = next_block.block_num();
578  uint32_t skip = get_node_properties().skip_flags;
579  _applied_ops.clear();
580 
581  if( !(skip & skip_block_size_check) )
582  {
583  FC_ASSERT( fc::raw::pack_size(next_block) <= get_global_properties().parameters.maximum_block_size );
584  }
585 
586  FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root(),
587  "",
588  ("next_block.transaction_merkle_root",next_block.transaction_merkle_root)
589  ("calc",next_block.calculate_merkle_root())
590  ("next_block",next_block)
591  ("id",next_block.id()) );
592 
593  const witness_object& signing_witness = validate_block_header(skip, next_block);
594  const auto& global_props = get_global_properties();
595  const auto& dynamic_global_props = get_dynamic_global_properties();
596  bool maint_needed = (dynamic_global_props.next_maintenance_time <= next_block.timestamp);
597 
598  // trx_in_block starts from 0.
599  // For real operations which are explicitly included in a transaction, op_in_trx starts from 0, virtual_op is 0.
600  // For virtual operations that are derived directly from a real operation,
601  // use the real operation's (block_num,trx_in_block,op_in_trx), virtual_op starts from 1.
602  // For virtual operations created after processed all transactions,
603  // trx_in_block = the_block.trsanctions.size(), op_in_trx is 0, virtual_op starts from 0.
604  _current_block_num = next_block_num;
605  _current_trx_in_block = 0;
606 
607  _issue_453_affected_assets.clear();
608 
609  for( const auto& trx : next_block.transactions )
610  {
611  /* We do not need to push the undo state for each transaction
612  * because they either all apply and are valid or the
613  * entire block fails to apply. We only need an "undo" state
614  * for transactions when validating broadcast transactions or
615  * when building a block.
616  */
617  apply_transaction( trx, skip );
618  ++_current_trx_in_block;
619  }
620 
621  _current_op_in_trx = 0;
622  _current_virtual_op = 0;
623 
624  const uint32_t missed = update_witness_missed_blocks( next_block );
625  update_global_dynamic_data( next_block, missed );
626  update_signing_witness(signing_witness, next_block);
627  update_last_irreversible_block();
628 
629  process_tickets();
630 
631  // Are we at the maintenance interval?
632  if( maint_needed )
633  perform_chain_maintenance(next_block, global_props);
634 
635  create_block_summary(next_block);
636  clear_expired_transactions();
637  clear_expired_proposals();
638  clear_expired_orders();
639  clear_expired_htlcs();
640  update_expired_feeds(); // this will update expired feeds and some core exchange rates
641  update_core_exchange_rates(); // this will update remaining core exchange rates
642  update_withdraw_permissions();
643 
644  // n.b., update_maintenance_flag() happens this late
645  // because get_slot_time() / get_slot_at_time() is needed above
646  // TODO: figure out if we could collapse this function into
647  // update_global_dynamic_data() as perhaps these methods only need
648  // to be called for header validation?
649  update_maintenance_flag( maint_needed );
651  if( !_node_property_object.debug_updates.empty() )
653 
654  // notify observers that the block has been applied
655  notify_applied_block( next_block ); //emit
656  _applied_ops.clear();
657 
659 } FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) }
660 
661 
662 
664 {
665  processed_transaction result;
666  detail::with_skip_flags( *this, skip, [&]()
667  {
668  result = _apply_transaction(trx);
669  });
670  return result;
671 }
672 
673 processed_transaction database::_apply_transaction(const signed_transaction& trx)
674 { try {
675  uint32_t skip = get_node_properties().skip_flags;
676 
677  trx.validate();
678 
679  auto& trx_idx = get_mutable_index_type<transaction_index>();
680  const chain_id_type& chain_id = get_chain_id();
681  if( !(skip & skip_transaction_dupe_check) )
682  {
683  GRAPHENE_ASSERT( trx_idx.indices().get<by_trx_id>().find(trx.id()) == trx_idx.indices().get<by_trx_id>().end(),
684  duplicate_transaction,
685  "Transaction '${txid}' is already in the database",
686  ("txid",trx.id()) );
687  }
688  transaction_evaluation_state eval_state(this);
690  eval_state._trx = &trx;
691 
692  if( !(skip & skip_transaction_signatures) )
693  {
694  bool allow_non_immediate_owner = ( head_block_time() >= HARDFORK_CORE_584_TIME );
695  auto get_active = [this]( account_id_type id ) { return &id(*this).active; };
696  auto get_owner = [this]( account_id_type id ) { return &id(*this).owner; };
697  auto get_custom = [this]( account_id_type id, const operation& op, rejected_predicate_map* rejects ) {
698  return get_viable_custom_authorities(id, op, rejects);
699  };
700 
701  trx.verify_authority(chain_id, get_active, get_owner, get_custom, allow_non_immediate_owner,
702  MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(head_block_time()),
703  get_global_properties().parameters.max_authority_depth);
704  }
705 
706  //Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
707  //expired, and TaPoS makes no sense as no blocks exist.
708  if( BOOST_LIKELY(head_block_num() > 0) )
709  {
710  if( !(skip & skip_tapos_check) )
711  {
712  const auto& tapos_block_summary = block_summary_id_type( trx.ref_block_num )(*this);
713 
714  //Verify TaPoS block summary has correct ID prefix, and that this block's time is not past the expiration
715  FC_ASSERT( trx.ref_block_prefix == tapos_block_summary.block_id._hash[1].value() );
716  }
717 
719 
720  FC_ASSERT( trx.expiration <= now + chain_parameters.maximum_time_until_expiration, "",
721  ("trx.expiration",trx.expiration)("now",now)("max_til_exp",chain_parameters.maximum_time_until_expiration));
722  FC_ASSERT( now <= trx.expiration, "", ("now",now)("trx.exp",trx.expiration) );
723  if ( !(skip & skip_block_size_check ) ) // don't waste time on replay
724  FC_ASSERT( head_block_time() <= HARDFORK_CORE_1573_TIME
725  || trx.get_packed_size() <= chain_parameters.maximum_transaction_size,
726  "Transaction exceeds maximum transaction size." );
727  }
728 
729  //Insert transaction into unique transactions database.
730  if( !(skip & skip_transaction_dupe_check) )
731  {
732  create<transaction_history_object>([&trx](transaction_history_object& transaction) {
733  transaction.trx_id = trx.id();
734  transaction.trx = trx;
735  });
736  }
737 
738  eval_state.operation_results.reserve(trx.operations.size());
739 
740  //Finally process the operations
741  processed_transaction ptrx(trx);
742  _current_op_in_trx = 0;
743  for( const auto& op : ptrx.operations )
744  {
745  _current_virtual_op = 0;
746  eval_state.operation_results.emplace_back(apply_operation(eval_state, op));
747  ++_current_op_in_trx;
748  }
749  ptrx.operation_results = std::move(eval_state.operation_results);
750 
751  return ptrx;
752 } FC_CAPTURE_AND_RETHROW( (trx) ) }
753 
755 { try {
756  int i_which = op.which();
757  uint64_t u_which = uint64_t( i_which );
758  FC_ASSERT( i_which >= 0, "Negative operation tag in operation ${op}", ("op",op) );
759  FC_ASSERT( u_which < _operation_evaluators.size(), "No registered evaluator for operation ${op}", ("op",op) );
760  unique_ptr<op_evaluator>& eval = _operation_evaluators[ u_which ];
761  FC_ASSERT( eval, "No registered evaluator for operation ${op}", ("op",op) );
762  auto op_id = push_applied_operation( op );
763  auto result = eval->evaluate( eval_state, op, true );
764  set_applied_operation_result( op_id, result );
765  return result;
766 } FC_CAPTURE_AND_RETHROW( (op) ) }
767 
768 const witness_object& database::validate_block_header( uint32_t skip, const signed_block& next_block )const
769 {
770  FC_ASSERT( head_block_id() == next_block.previous, "", ("head_block_id",head_block_id())("next.prev",next_block.previous) );
771  FC_ASSERT( head_block_time() < next_block.timestamp, "", ("head_block_time",head_block_time())("next",next_block.timestamp)("blocknum",next_block.block_num()) );
772  const witness_object& witness = next_block.witness(*this);
773 
774  if( !(skip&skip_witness_signature) )
775  FC_ASSERT( next_block.validate_signee( witness.signing_key ) );
776 
777  if( !(skip&skip_witness_schedule_check) )
778  {
779  uint32_t slot_num = get_slot_at_time( next_block.timestamp );
780  FC_ASSERT( slot_num > 0 );
781 
782  witness_id_type scheduled_witness = get_scheduled_witness( slot_num );
783 
784  FC_ASSERT( next_block.witness == scheduled_witness, "Witness produced block at wrong time",
785  ("block witness",next_block.witness)("scheduled",scheduled_witness)("slot_num",slot_num) );
786  }
787 
788  return witness;
789 }
790 
791 void database::create_block_summary(const signed_block& next_block)
792 {
793  block_summary_id_type sid(next_block.block_num() & 0xffff );
794  modify( sid(*this), [&](block_summary_object& p) {
795  p.block_id = next_block.id();
796  });
797 }
798 
799 void database::add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts )
800 {
801  for( const auto& i : checkpts )
802  _checkpoints[i.first] = i.second;
803 }
804 
806 {
807  return (_checkpoints.size() > 0) && (_checkpoints.rbegin()->first >= head_block_num());
808 }
809 
810 
811 static const uint32_t skip_expensive = database::skip_transaction_signatures | database::skip_witness_signature
813 
814 template<typename Trx>
815 void database::_precompute_parallel( const Trx* trx, const size_t count, const uint32_t skip )const
816 {
817  for( size_t i = 0; i < count; ++i, ++trx )
818  {
819  trx->validate(); // TODO - parallelize wrt confidential operations
820  if ( !(skip & skip_block_size_check) )
821  trx->get_packed_size();
822  if( !(skip&skip_transaction_dupe_check) )
823  trx->id();
824  if( !(skip&skip_transaction_signatures) )
825  trx->get_signature_keys( get_chain_id() );
826  }
827 }
828 
829 fc::future<void> database::precompute_parallel( const signed_block& block, const uint32_t skip )const
830 { try {
831  std::vector<fc::future<void>> workers;
832  if( !block.transactions.empty() )
833  {
834  if( (skip & skip_expensive) == skip_expensive )
835  _precompute_parallel( &block.transactions[0], block.transactions.size(), skip );
836  else
837  {
839  uint32_t chunk_size = ( block.transactions.size() + chunks - 1 ) / chunks;
840  workers.reserve( chunks + 1 );
841  for( size_t base = 0; base < block.transactions.size(); base += chunk_size )
842  workers.push_back( fc::do_parallel( [this,&block,base,chunk_size,skip] () {
843  _precompute_parallel( &block.transactions[base],
844  base + chunk_size < block.transactions.size() ? chunk_size : block.transactions.size() - base,
845  skip );
846  }) );
847  }
848  }
849 
850  if( !(skip&skip_witness_signature) )
851  workers.push_back( fc::do_parallel( [&block] () { block.signee(); } ) );
852  if( !(skip&skip_merkle_check) )
853  block.calculate_merkle_root();
854  block.id();
855 
856  if( workers.empty() )
858 
859  auto first = workers.begin();
860  auto worker = first;
861  while( ++worker != workers.end() )
862  worker->wait();
863  return *first;
864 } FC_LOG_AND_RETHROW() }
865 
867 {
868  return fc::do_parallel([this,&trx] () {
869  _precompute_parallel( &trx, 1, skip_nothing );
870  });
871 }
872 
873 } }
bool is_known_transaction(const transaction_id_type &id) const
Definition: db_block.cpp:56
shared_ptr< fork_item > item_ptr
fc::time_point_sec timestamp
Definition: block.hpp:35
void sign(const fc::ecc::private_key &signer)
Definition: block.cpp:60
void modify(const T &obj, const Lambda &m)
push_proposal_nesting_guard(uint32_t &nesting_counter, const database &db)
Definition: db_block.cpp:312
uint32_t sec_since_epoch() const
Definition: time.hpp:55
virtual const transaction_id_type & id() const
Definition: transaction.cpp:70
const T * find(object_id_type id) const
bool is_known_block(const block_id_type &id) const
Definition: db_block.cpp:47
fc::time_point_sec expiration
Definition: transaction.hpp:87
shared_ptr< fork_item > fetch_block(const block_id_type &id) const
bool before_last_checkpoint() const
Definition: db_block.cpp:805
block_id_type get_block_id_for_num(uint32_t block_num) const
Definition: db_block.cpp:62
pair< branch_type, branch_type > fetch_branch_from(block_id_type first, block_id_type second) const
map< custom_authority_id_type, rejected_predicate > rejected_predicate_map
Definition: transaction.hpp:31
processed_transaction apply_transaction(const signed_transaction &trx, uint32_t skip=skip_nothing)
Definition: db_block.cpp:663
vector< operation > operations
Definition: transaction.hpp:89
void verify_authority(const chain_id_type &chain_id, const std::function< const authority *(account_id_type)> &get_active, const std::function< const authority *(account_id_type)> &get_owner, const custom_authority_lookup &get_custom, bool allow_non_immediate_owner, bool ignore_custom_operation_required_auths, uint32_t max_recursion=GRAPHENE_MAX_SIG_CHECK_DEPTH) const
uint32_t sec_since_epoch() const
Definition: time.hpp:90
tracks the history of all logical operations on blockchain stateAll operations and virtual operations...
virtual void validate() const
Definition: transaction.cpp:58
void notify_applied_block(const signed_block &block)
Definition: db_notify.cpp:495
Maintains global state information (committee_member list, current fees)This is an implementation det...
const witness_schedule_object & get_witness_schedule_object() const
Definition: db_getter.cpp:144
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:56
#define elog(FORMAT,...)
Definition: logger.hpp:129
bool validate_signee(const fc::ecc::public_key &expected_signee) const
Definition: block.cpp:65
fc::future< void > precompute_parallel(const signed_block &block, const uint32_t skip=skip_nothing) const
Definition: db_block.cpp:829
processed_transaction push_proposal(const proposal_object &proposal)
Definition: db_block.cpp:328
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
std::string to_detail_string(log_level ll=log_level::all) const
Definition: exception.cpp:183
uint32_t maximum_transaction_size
maximum allowable size in bytes for a transaction
const dynamic_global_property_object & get_dynamic_global_properties() const
Definition: db_getter.cpp:54
fc::static_variant< transfer_operation, limit_order_create_operation, limit_order_cancel_operation, call_order_update_operation, fill_order_operation, account_create_operation, account_update_operation, account_whitelist_operation, account_upgrade_operation, account_transfer_operation, asset_create_operation, asset_update_operation, asset_update_bitasset_operation, asset_update_feed_producers_operation, asset_issue_operation, asset_reserve_operation, asset_fund_fee_pool_operation, asset_settle_operation, asset_global_settle_operation, asset_publish_feed_operation, witness_create_operation, witness_update_operation, proposal_create_operation, proposal_update_operation, proposal_delete_operation, withdraw_permission_create_operation, withdraw_permission_update_operation, withdraw_permission_claim_operation, withdraw_permission_delete_operation, committee_member_create_operation, committee_member_update_operation, committee_member_update_global_parameters_operation, vesting_balance_create_operation, vesting_balance_withdraw_operation, worker_create_operation, custom_operation, assert_operation, balance_claim_operation, override_transfer_operation, transfer_to_blind_operation, blind_transfer_operation, transfer_from_blind_operation, asset_settle_cancel_operation, asset_claim_fees_operation, fba_distribute_operation, bid_collateral_operation, execute_bid_operation, asset_claim_pool_operation, asset_update_issuer_operation, htlc_create_operation, htlc_redeem_operation, htlc_redeemed_operation, htlc_extend_operation, htlc_refund_operation, custom_authority_create_operation, custom_authority_update_operation, custom_authority_delete_operation, ticket_create_operation, ticket_update_operation >
void set_applied_operation_result(uint32_t op_id, const operation_result &r)
Definition: db_block.cpp:537
void with_skip_flags(database &db, uint32_t skip_flags, Lambda callback)
Definition: db_with.hpp:113
auto do_parallel(Functor &&f, const char *desc FC_TASK_NAME_DEFAULT_ARG) -> fc::future< decltype(f())>
Definition: parallel.hpp:97
signed_block _generate_block(const fc::time_point_sec when, witness_id_type witness_id, const fc::ecc::private_key &block_signing_private_key)
Definition: db_block.cpp:383
uint32_t head_block_num() const
Definition: db_getter.cpp:69
signed_block generate_block(const fc::time_point_sec when, witness_id_type witness_id, const fc::ecc::private_key &block_signing_private_key, uint32_t skip)
Definition: db_block.cpp:368
groups operations that should be applied atomically
Definition: transaction.hpp:68
void without_pending_transactions(database &db, std::vector< processed_transaction > &&pending_transactions, Lambda callback)
Definition: db_with.hpp:132
#define wlog(FORMAT,...)
Definition: logger.hpp:123
bool push_block(const signed_block &b, uint32_t skip=skip_nothing)
Definition: db_block.cpp:116
char * data() const
Definition: ripemd160.cpp:26
const global_property_object & get_global_properties() const
Definition: db_getter.cpp:44
tag_type which() const
vector< item_ptr > fetch_block_by_number(uint32_t n) const
fc::ripemd160 block_id_type
Definition: types.hpp:242
public_key get_public_key() const
optional< signed_block > fetch_block_by_number(uint32_t num) const
Definition: db_block.cpp:75
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
vector< authority > get_viable_custom_authorities(account_id_type account, const operation &op, rejected_predicate_map *rejected_authorities=nullptr) const
Get a list of custom authorities which can validate the provided operation for the provided account...
Definition: db_getter.cpp:99
checksum_type transaction_merkle_root
Definition: block.hpp:37
virtual uint64_t get_packed_size() const
Definition: transaction.cpp:65
uint32_t get_slot_at_time(fc::time_point_sec when) const
vector< operation_result > operation_results
size_t pack_size(const T &v)
Definition: raw.hpp:757
std::size_t size() const
void set_max_size(size_t new_max_size)
void apply_block(const signed_block &next_block, uint32_t skip=skip_nothing)
Definition: db_block.cpp:555
virtual const object * find(object_id_type id) const =0
const vector< optional< operation_history_object > > & get_applied_operations() const
Definition: db_block.cpp:548
operation_result apply_operation(transaction_evaluation_state &eval_state, const operation &op)
Definition: db_block.cpp:754
void notify_on_pending_transaction(const signed_transaction &tx)
Definition: db_notify.cpp:500
processed_transaction _push_transaction(const precomputable_transaction &trx)
Definition: db_block.cpp:279
block_id_type fetch_block_id(uint32_t block_num) const
const fc::ecc::public_key & signee() const
Definition: block.cpp:53
uint32_t push_applied_operation(const operation &op)
Definition: db_block.cpp:527
#define edump(SEQ)
Definition: logger.hpp:182
void set_head(shared_ptr< fork_item > h)
std::vector< block_id_type > get_block_ids_on_fork(block_id_type head_of_fork) const
Definition: db_block.cpp:92
time_point_sec head_block_time() const
Definition: db_getter.cpp:64
#define ilog(FORMAT,...)
Definition: logger.hpp:117
const node_property_object & get_node_properties() const
Definition: db_getter.cpp:89
processed_transaction validate_transaction(const signed_transaction &trx)
Definition: db_block.cpp:304
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
shared_ptr< fork_item > push_block(const signed_block &b)
shared_ptr< vector< pair< witness_id_type, public_key_type > > > scheduled_witnesses
adds a signature to a transaction
static uint16_t get_num_threads()
Definition: asio.cpp:108
uint32_t maximum_time_until_expiration
maximum lifetime in seconds for transactions to be valid, before expiring
fc::time_point_sec next_block_time
at< List, 0 > first
Get the type at the beginning of the list.
Definition: typelist.hpp:190
session start_undo_session(bool force_enable=false)
shared_ptr< fork_item > head() const
used while reindexing – note this skips expiration check as well
Definition: database.hpp:85
optional< signed_block > fetch_optional(const block_id_type &id) const
processed_transaction push_transaction(const precomputable_transaction &trx, uint32_t skip=skip_nothing)
Definition: db_block.cpp:267
const checksum_type & calculate_merkle_root() const
Definition: block.cpp:70
std::deque< precomputable_transaction > _popped_tx
Definition: database.hpp:511
void remove(block_id_type b)
void store(const block_id_type &id, const signed_block &b)
bool contains(const block_id_type &id) const
const object & get(object_id_type id) const
Definition: index.hpp:111
generic_operation_result process_tickets()
Definition: db_update.cpp:605
uint32_t block_num() const
Definition: block.hpp:34
tracks minimal information about past blocks to implement TaPOSWhen attempting to calculate the valid...
const signed_transaction & get_recent_transaction(const transaction_id_type &trx_id) const
Definition: db_block.cpp:84
abstract base class for accessing objects indexed in various ways.
Definition: index.hpp:71
optional< signed_block > fetch_by_number(uint32_t block_num) const
#define GRAPHENE_ASSERT(expr, exc_type, FORMAT,...)
Definition: exceptions.hpp:28
const block_id_type & id() const
Definition: block.cpp:41
bool _push_block(const signed_block &b)
Definition: db_block.cpp:131
static time_point now()
Definition: time.cpp:13
const chain_id_type & get_chain_id() const
Definition: db_getter.cpp:84
an elliptic curve private key.
Definition: elliptic.hpp:89
void add_checkpoints(const flat_map< uint32_t, block_id_type > &checkpts)
Definition: db_block.cpp:799
block_id_type head_block_id() const
Definition: db_getter.cpp:74
bool is_known_block(const block_id_type &id) const
#define FC_LOG_AND_RETHROW()
Definition: exception.hpp:394
vector< processed_transaction > transactions
Definition: block.hpp:63
captures the result of evaluating the operations contained in the transaction
uint32_t maximum_block_size
maximum allowable size in bytes for a block
witness_id_type get_scheduled_witness(uint32_t slot_num) const
Get the witness scheduled for block production in a slot.
fc::time_point_sec get_slot_time(uint32_t slot_num) const
used when applying locally generated transactions
Definition: database.hpp:84
optional< signed_block > fetch_block_by_id(const block_id_type &id) const
Definition: db_block.cpp:67
tracks the approval of a partially approved transaction