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