chain_controller.cpp 95.3 KB
Newer Older
A
Andrianto Lie 已提交
1 2 3
/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
N
Nathan Hourt 已提交
4
 */
N
Nathan Hourt 已提交
5

B
Bart Wyatt 已提交
6
#include <eosio/chain/chain_controller.hpp>
N
Nathan Hourt 已提交
7

B
Bart Wyatt 已提交
8 9
#include <eosio/chain/block_summary_object.hpp>
#include <eosio/chain/global_property_object.hpp>
10
#include <eosio/chain/contracts/contract_table_objects.hpp>
B
Bart Wyatt 已提交
11 12 13 14 15 16
#include <eosio/chain/action_objects.hpp>
#include <eosio/chain/generated_transaction_object.hpp>
#include <eosio/chain/transaction_object.hpp>
#include <eosio/chain/producer_object.hpp>
#include <eosio/chain/permission_link_object.hpp>
#include <eosio/chain/authority_checker.hpp>
D
Daniel Larimer 已提交
17
#include <eosio/chain/contracts/chain_initializer.hpp>
18
#include <eosio/chain/scope_sequence_object.hpp>
19
#include <eosio/chain/merkle.hpp>
N
Nathan Hourt 已提交
20

21
#include <eosio/chain/exceptions.hpp>
B
Bart Wyatt 已提交
22
#include <eosio/chain/wasm_interface.hpp>
23

24
#include <eosio/utilities/rand.hpp>
25

N
Nathan Hourt 已提交
26
#include <fc/smart_ref_impl.hpp>
N
Nathan Hourt 已提交
27 28 29
#include <fc/uint128.hpp>
#include <fc/crypto/digest.hpp>

30
#include <boost/range/algorithm/copy.hpp>
31
#include <boost/range/algorithm_ext/erase.hpp>
N
Nathan Hourt 已提交
32
#include <boost/range/algorithm_ext/is_sorted.hpp>
33
#include <boost/range/adaptor/transformed.hpp>
N
Nathan Hourt 已提交
34
#include <boost/range/adaptor/map.hpp>
35 36 37 38
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/find.hpp>
#include <boost/range/algorithm/remove_if.hpp>
#include <boost/range/algorithm/equal.hpp>
N
Nathan Hourt 已提交
39 40 41

#include <fstream>
#include <functional>
42
#include <chrono>
N
Nathan Hourt 已提交
43

P
Pravin 已提交
44
namespace eosio { namespace chain {
D
Daniel Larimer 已提交
45

46 47 48 49 50
bool chain_controller::is_start_of_round( block_num_type block_num )const  {
  return 0 == (block_num % blocks_per_round());
}

uint32_t chain_controller::blocks_per_round()const {
51
  return get_global_properties().active_producers.producers.size()*config::producer_repetitions;
52 53
}

D
Daniel Larimer 已提交
54
chain_controller::chain_controller( const chain_controller::controller_config& cfg )
55 56 57
:_db( cfg.shared_memory_dir,
      (cfg.read_only ? database::read_only : database::read_write),
      cfg.shared_memory_size),
58
 _block_log(cfg.block_log_dir),
59
 _wasm_interface(cfg.wasm_runtime),
B
Bart Wyatt 已提交
60
 _limits(cfg.limits),
61
 _resource_limits(_db)
D
Daniel Larimer 已提交
62 63
{
   _initialize_indexes();
64 65
   _resource_limits.initialize_database();

D
Daniel Larimer 已提交
66

67 68
   for (auto& f : cfg.applied_block_callbacks)
      applied_block.connect(f);
69 70
   for (auto& f : cfg.applied_irreversible_block_callbacks)
      applied_irreversible_block.connect(f);
71 72
   for (auto& f : cfg.on_pending_transaction_callbacks)
      on_pending_transaction.connect(f);
73

D
Daniel Larimer 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
   contracts::chain_initializer starter(cfg.genesis);
   starter.register_types(*this, _db);

   // Behave as though we are applying a block during chain initialization (it's the genesis block!)
   with_applying_block([&] {
      _initialize_chain(starter);
   });

   _spinup_db();
   _spinup_fork_db();

   if (_block_log.read_head() && head_block_num() < _block_log.read_head()->block_num())
      replay();
} /// chain_controller::chain_controller


chain_controller::~chain_controller() {
   clear_pending();
   _db.flush();
}

95
bool chain_controller::is_known_block(const block_id_type& id)const
N
Nathan Hourt 已提交
96
{
97
   return _fork_db.is_known_block(id) || _block_log.read_block_by_id(id);
N
Nathan Hourt 已提交
98 99 100 101 102 103
}
/**
 * Only return true *if* the transaction has not expired or been invalidated. If this
 * method is called with a VERY old transaction we will return false, they should
 * query things by blocks if they are that old.
 */
104
bool chain_controller::is_known_transaction(const transaction_id_type& id)const
N
Nathan Hourt 已提交
105
{
106
   const auto& trx_idx = _db.get_index<transaction_multi_index, by_trx_id>();
N
Nathan Hourt 已提交
107 108 109
   return trx_idx.find( id ) != trx_idx.end();
}

110
block_id_type chain_controller::get_block_id_for_num(uint32_t block_num)const
N
Nathan Hourt 已提交
111
{ try {
112 113
   if (const auto& block = fetch_block_by_number(block_num))
      return block->id();
N
Nathan Hourt 已提交
114

115 116 117
   FC_THROW_EXCEPTION(unknown_block_exception, "Could not find block");
} FC_CAPTURE_AND_RETHROW((block_num)) }

118
optional<signed_block> chain_controller::fetch_block_by_id(const block_id_type& id)const
N
Nathan Hourt 已提交
119
{
120 121
   auto b = _fork_db.fetch_block(id);
   if(b) return b->data;
122
   return _block_log.read_block_by_id(id);
N
Nathan Hourt 已提交
123 124
}

125
optional<signed_block> chain_controller::fetch_block_by_number(uint32_t num)const
N
Nathan Hourt 已提交
126
{
127
   if (const auto& block = _block_log.read_block_by_num(num))
128 129
      return *block;

N
Nathan Hourt 已提交
130
   // Not in _block_log, so it must be since the last irreversible block. Grab it from _fork_db instead
131 132 133 134 135 136 137 138
   if (num <= head_block_num()) {
      auto block = _fork_db.head();
      while (block && block->num > num)
         block = block->prev.lock();
      if (block && block->num == num)
         return block->data;
   }

N
Nathan Hourt 已提交
139 140 141
   return optional<signed_block>();
}

142
std::vector<block_id_type> chain_controller::get_block_ids_on_fork(block_id_type head_of_fork) const
N
Nathan Hourt 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
{
  pair<fork_database::branch_type, fork_database::branch_type> branches = _fork_db.fetch_branch_from(head_block_id(), head_of_fork);
  if( !((branches.first.back()->previous_id() == branches.second.back()->previous_id())) )
  {
     edump( (head_of_fork)
            (head_block_id())
            (branches.first.size())
            (branches.second.size()) );
     assert(branches.first.back()->previous_id() == branches.second.back()->previous_id());
  }
  std::vector<block_id_type> result;
  for (const item_ptr& fork_block : branches.second)
    result.emplace_back(fork_block->id);
  result.emplace_back(branches.first.back()->previous_id());
  return result;
}

160

N
Nathan Hourt 已提交
161 162 163 164 165 166
/**
 * Push block "may fail" in which case every partial change is unwound.  After
 * push block is successful the block is appended to the chain database on disk.
 *
 * @return true if we switched forks as a result of this push.
 */
D
Daniel Larimer 已提交
167
void chain_controller::push_block(const signed_block& new_block, uint32_t skip)
D
Daniel Larimer 已提交
168
{ try {
169
   with_skip_flags( skip, [&](){
D
Daniel Larimer 已提交
170
      return without_pending_transactions( [&]() {
171
         return _db.with_write_lock( [&]() {
172
            return _push_block(new_block);
173
         } );
N
Nathan Hourt 已提交
174 175
      });
   });
176
   ilog( "\rpush block #${n} from ${pro} ${time}  ${id} lib: ${l} success", ("n",new_block.block_num())("pro",name(new_block.producer))("time",new_block.timestamp)("id",new_block.id())("l",last_irreversible_block_num()));
177
} FC_CAPTURE_AND_RETHROW((new_block)) }
N
Nathan Hourt 已提交
178

179
bool chain_controller::_push_block(const signed_block& new_block)
N
Nathan Hourt 已提交
180
{ try {
N
Nathan Hourt 已提交
181
   uint32_t skip = _skip_flags;
182
   if (!(skip&skip_fork_db)) {
N
Nathan Hourt 已提交
183
      /// TODO: if the block is greater than the head block and before the next maintenance interval
N
Nathan Hourt 已提交
184 185 186 187
      // verify that the block signer is in the current set of active producers.

      shared_ptr<fork_item> new_head = _fork_db.push_block(new_block);
      //If the head block from the longest chain does not build off of the current head, we need to switch forks.
188
      if (new_head->data.previous != head_block_id()) {
N
Nathan Hourt 已提交
189 190
         //If the newly pushed block is the same height as head, we get head back in new_head
         //Only switch forks if new_head is actually higher than head
191 192
         if (new_head->data.block_num() > head_block_num()) {
            wlog("Switching to fork: ${id}", ("id",new_head->data.id()));
N
Nathan Hourt 已提交
193 194 195
            auto branches = _fork_db.fetch_branch_from(new_head->data.id(), head_block_id());

            // pop blocks until we hit the forked block
196
            while (head_block_id() != branches.second.back()->data.previous)
N
Nathan Hourt 已提交
197 198 199
               pop_block();

            // push all blocks on the new fork
200 201
            for (auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr) {
                ilog("pushing blocks from fork ${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->data.id()));
202 203 204 205 206 207 208
                {
                   uint32_t delta = 0;
                   if (ritr != branches.first.rbegin()) {
                      delta = (*ritr)->data.timestamp.slot - (*std::prev(ritr))->data.timestamp.slot;
                   } else {
                      optional<signed_block> prev = fetch_block_by_id((*ritr)->data.previous);
                      if (prev)
K
Khaled Al-Hassanieh 已提交
209
                         delta = (*ritr)->data.timestamp.slot - prev->timestamp.slot;
210 211 212 213
                   }
                   if (delta > 1)
                      wlog("Number of missed blocks: ${num}", ("num", delta-1));
                }
N
Nathan Hourt 已提交
214 215
                optional<fc::exception> except;
                try {
216
                   auto session = _db.start_undo_session(true);
D
Daniel Larimer 已提交
217
                   _apply_block((*ritr)->data, skip);
N
Nathan Hourt 已提交
218 219
                   session.push();
                }
220 221 222
                catch (const fc::exception& e) { except = e; }
                if (except) {
                   wlog("exception thrown while switching forks ${e}", ("e",except->to_detail_string()));
N
Nathan Hourt 已提交
223
                   // remove the rest of branches.first from the fork_db, those blocks are invalid
224 225
                   while (ritr != branches.first.rend()) {
                      _fork_db.remove((*ritr)->data.id());
N
Nathan Hourt 已提交
226 227
                      ++ritr;
                   }
228
                   _fork_db.set_head(branches.second.front());
N
Nathan Hourt 已提交
229 230

                   // pop all blocks from the bad fork
231
                   while (head_block_id() != branches.second.back()->data.previous)
N
Nathan Hourt 已提交
232 233 234
                      pop_block();

                   // restore all blocks from the good fork
235
                   for (auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr) {
236
                      auto session = _db.start_undo_session(true);
D
Daniel Larimer 已提交
237
                      _apply_block((*ritr)->data, skip);
N
Nathan Hourt 已提交
238 239 240 241 242
                      session.push();
                   }
                   throw *except;
                }
            }
D
Daniel Larimer 已提交
243
            return true; //swithced fork
N
Nathan Hourt 已提交
244
         }
D
Daniel Larimer 已提交
245
         else return false; // didn't switch fork
N
Nathan Hourt 已提交
246 247 248 249
      }
   }

   try {
250
      auto session = _db.start_undo_session(true);
D
Daniel Larimer 已提交
251
      _apply_block(new_block, skip);
N
Nathan Hourt 已提交
252 253 254 255 256 257 258 259
      session.push();
   } catch ( const fc::exception& e ) {
      elog("Failed to push new block:\n${e}", ("e", e.to_detail_string()));
      _fork_db.remove(new_block.id());
      throw;
   }

   return false;
260
} FC_CAPTURE_AND_RETHROW((new_block)) }
N
Nathan Hourt 已提交
261 262 263 264 265 266 267 268 269 270

/**
 * Attempts to push the transaction into the pending queue
 *
 * When called to push a locally generated transaction, set the skip_block_size_check bit on the skip argument. This
 * will allow the transaction to be pushed even if it causes the pending block size to exceed the maximum block size.
 * Although the transaction will probably not propagate further now, as the peers are likely to have their pending
 * queues full as well, it will be kept in the queue to be propagated later when a new block flushes out the pending
 * queues.
 */
271
transaction_trace chain_controller::push_transaction(const packed_transaction& trx, uint32_t skip)
N
Nathan Hourt 已提交
272
{ try {
273 274 275 276 277 278
   // If this is the first transaction pushed after applying a block, start a new undo session.
   // This allows us to quickly rewind to the clean state of the head block, in case a new block arrives.
   if( !_pending_block ) {
      _start_pending_block();
   }

279 280
   return with_skip_flags(skip, [&]() {
      return _db.with_write_lock([&]() {
281
         return _push_transaction(trx);
D
Daniel Larimer 已提交
282
      });
N
Nathan Hourt 已提交
283
   });
284
} EOS_CAPTURE_AND_RETHROW( transaction_exception ) }
N
Nathan Hourt 已提交
285

286
transaction_trace chain_controller::_push_transaction(const packed_transaction& packed_trx)
287
{ try {
288
   //edump((transaction_header(packed_trx.get_transaction())));
289
   auto start = fc::time_point::now();
290
   transaction_metadata   mtrx( packed_trx, get_chain_id(), head_block_time());
291
   //idump((transaction_header(mtrx.trx())));
292

293
   const transaction& trx = mtrx.trx();
294 295
   mtrx.delay =  fc::seconds(trx.delay_sec);

296
   validate_transaction_with_minimal_state( trx, mtrx.billable_packed_size );
297
   validate_expiration_not_too_far(trx, head_block_time() + mtrx.delay);
298 299
   validate_referenced_accounts(trx);
   validate_uniqueness(trx);
300 301 302 303 304 305 306
   if( should_check_authorization() ) {
      auto enforced_delay = check_transaction_authorization(trx, packed_trx.signatures, mtrx.context_free_data);
      EOS_ASSERT( mtrx.delay >= enforced_delay,
                  transaction_exception,
                  "authorization imposes a delay (${enforced_delay} sec) greater than the delay specified in transaction header (${specified_delay} sec)",
                  ("enforced_delay", enforced_delay.to_seconds())("specified_delay", mtrx.delay.to_seconds()) );
   }
307

308
   auto setup_us = fc::time_point::now() - start;
309

310
   transaction_trace result(mtrx.id);
B
Bart Wyatt 已提交
311

312
   if( mtrx.delay.count() == 0 ) {
313
      result = _push_transaction( std::move(mtrx) );
314 315
   } else {

316 317 318
      result = wrap_transaction_processing( std::move(mtrx),
                                            [this](transaction_metadata& meta) { return delayed_transaction_processing(meta); } );
   }
319

320 321
   // notify anyone listening to pending transactions
   on_pending_transaction(_pending_transaction_metas.back(), packed_trx);
B
Bart Wyatt 已提交
322

323
   _pending_block->input_transactions.emplace_back(packed_trx);
B
Bart Wyatt 已提交
324

H
Harry 已提交
325
   result._setup_profiling_us = setup_us;
326
   return result;
327

328 329 330 331 332 333 334 335 336 337 338 339 340
} FC_CAPTURE_AND_RETHROW( (transaction_header(packed_trx.get_transaction())) ) }

transaction_trace chain_controller::_push_transaction( transaction_metadata&& data )
{ try {
   auto process_apply_transaction = [this](transaction_metadata& meta) {
      auto cyclenum = _pending_block->regions.back().cycles_summary.size() - 1;
      //wdump((transaction_header(meta.trx())));

      const auto& trx = meta.trx();

      // Validate uniqueness and expiration again
      validate_uniqueness(trx);
      validate_not_expired(trx);
341

342 343 344 345 346 347 348 349 350 351 352 353 354
      /// TODO: move _pending_cycle into db so that it can be undone if transation fails, for now we will apply
      /// the transaction first so that there is nothing to undo... this only works because things are currently
      /// single threaded
      // set cycle, shard, region etc
      meta.region_id = 0;
      meta.cycle_index = cyclenum;
      meta.shard_index = 0;
      return _apply_transaction( meta );
   };
 //  wdump((transaction_header(data.trx())));
   return wrap_transaction_processing( move(data), process_apply_transaction );
} FC_CAPTURE_AND_RETHROW( ) }

355 356 357 358 359
uint128_t chain_controller::transaction_id_to_sender_id( const transaction_id_type& tid )const {
   fc::uint128_t _id(tid._hash[3], tid._hash[2]);
   return (unsigned __int128)_id;
}

360 361 362 363 364 365 366 367 368
transaction_trace chain_controller::delayed_transaction_processing( const transaction_metadata& mtrx )
{ try {
   transaction_trace result(mtrx.id);
   result.status = transaction_trace::delayed;

   const auto& trx = mtrx.trx();

   time_point_sec execute_after = head_block_time();
   execute_after += mtrx.delay;
369 370

   // TODO: update to better method post RC1?
371
   account_name payer;
372
   for(const auto& act : trx.actions ) {
373 374
      if (act.authorization.size() > 0) {
         payer = act.authorization.at(0).actor;
375 376 377 378 379
         break;
      }
   }

   FC_ASSERT(!payer.empty(), "Failed to find a payer for delayed transaction!");
380

381 382
   update_resource_usage(result, mtrx);

383 384 385 386 387 388 389 390 391
   auto sender_id = transaction_id_to_sender_id( mtrx.id );

   const auto& generated_index = _db.get_index<generated_transaction_multi_index, by_sender_id>();
   auto colliding_trx = generated_index.find(boost::make_tuple(config::system_account_name, sender_id));
   FC_ASSERT( colliding_trx == generated_index.end(),
              "sender_id conflict between two delayed transactions: ${cur_trx_id} and ${prev_trx_id}",
              ("cur_trx_id", mtrx.id)("prev_trx_id", colliding_trx->trx_id) );

   deferred_transaction dtrx(sender_id, config::system_account_name, payer, execute_after, trx);
392 393 394 395 396
   FC_ASSERT( dtrx.execute_after < dtrx.expiration, "transaction expires before it can execute" );

   result.deferred_transaction_requests.push_back(std::move(dtrx));

   _create_generated_transaction(result.deferred_transaction_requests[0].get<deferred_transaction>());
397

B
Bart Wyatt 已提交
398 399
   return result;

400
} FC_CAPTURE_AND_RETHROW( ) }
B
Bart Wyatt 已提交
401

B
Bart Wyatt 已提交
402
static void record_locks_for_data_access(transaction_trace& trace, flat_set<shard_lock>& read_locks, flat_set<shard_lock>& write_locks ) {
403 404
   // Precondition: read_locks and write_locks do not intersect.

B
Bart Wyatt 已提交
405
   for (const auto& at: trace.action_traces) {
B
Bart Wyatt 已提交
406 407
      for (const auto& access: at.data_access) {
         if (access.type == data_access_info::read) {
B
Bart Wyatt 已提交
408
            trace.read_locks.emplace(shard_lock{access.code, access.scope});
B
Bart Wyatt 已提交
409
         } else {
B
Bart Wyatt 已提交
410
            trace.write_locks.emplace(shard_lock{access.code, access.scope});
B
Bart Wyatt 已提交
411 412 413
         }
      }
   }
B
Bart Wyatt 已提交
414

415
   // Step RR: Remove from trace.read_locks and from read_locks only the read locks necessary to ensure they each do not intersect with trace.write_locks.
416
   std::for_each(trace.write_locks.begin(), trace.write_locks.end(), [&]( const shard_lock& l){
417 418 419 420 421 422 423 424 425 426 427
      trace.read_locks.erase(l); read_locks.erase(l); // for step RR
      // write_locks.insert(l); // Step AW could instead be done here, but it would add unnecessary work to the lookups in step AR.
    });

   // At this point, the trace.read_locks and trace.write_locks are good.

   // Step AR: Add into read_locks the subset of trace.read_locks that does not intersect with write_locks (must occur after step RR).
   //          (Works regardless of whether step AW is done before or after this step.)
   std::for_each(trace.read_locks.begin(), trace.read_locks.end(), [&]( const shard_lock& l){
      if( write_locks.find(l) == write_locks.end() )
         read_locks.insert(l);
428
   });
B
Bart Wyatt 已提交
429

430 431

   // Step AW: Add trace.write_locks into write_locks.
B
Bart Wyatt 已提交
432
   write_locks.insert(trace.write_locks.begin(), trace.write_locks.end());
433 434 435

   // Postcondition: read_locks and write_locks do not intersect
   // Postcondition: trace.read_locks and trace.write_locks do not intersect
B
Bart Wyatt 已提交
436 437
}

K
Khaled Al-Hassanieh 已提交
438 439 440 441
block_header chain_controller::head_block_header() const
{
   auto b = _fork_db.fetch_block(head_block_id());
   if( b ) return b->data;
442

K
Khaled Al-Hassanieh 已提交
443 444 445 446
   if (auto head_block = fetch_block_by_id(head_block_id()))
      return *head_block;
   return block_header();
}
447

448
void chain_controller::_start_pending_block( bool skip_deferred )
449 450 451 452 453
{
   FC_ASSERT( !_pending_block );
   _pending_block         = signed_block();
   _pending_block_trace   = block_trace(*_pending_block);
   _pending_block_session = _db.start_undo_session(true);
454 455
   _pending_block->regions.resize(1);
   _pending_block_trace->region_traces.resize(1);
456

457
   _start_pending_cycle();
458
   _apply_on_block_transaction();
459
   _finalize_pending_cycle();
460

461
   _start_pending_cycle();
462 463

   if ( !skip_deferred ) {
A
Anton Perkov 已提交
464 465
      _push_deferred_transactions( false );
      if (_pending_cycle_trace && _pending_cycle_trace->shard_traces.size() > 0 && _pending_cycle_trace->shard_traces.back().transaction_traces.size() > 0) {
466 467 468
         _finalize_pending_cycle();
         _start_pending_cycle();
      }
469
   }
470 471
}

K
Khaled Al-Hassanieh 已提交
472
transaction chain_controller::_get_on_block_transaction()
473 474 475 476 477
{
   action on_block_act;
   on_block_act.account = config::system_account_name;
   on_block_act.name = N(onblock);
   on_block_act.authorization = vector<permission_level>{{config::system_account_name, config::active_name}};
478
   on_block_act.data = fc::raw::pack(head_block_header());
479 480 481 482

   transaction trx;
   trx.actions.emplace_back(std::move(on_block_act));
   trx.set_reference_block(head_block_id());
483
   trx.expiration = head_block_time() + fc::seconds(1);
484 485 486 487 488
   return trx;
}

void chain_controller::_apply_on_block_transaction()
{
489
   _pending_block_trace->implicit_transactions.emplace_back(_get_on_block_transaction());
490
   transaction_metadata mtrx(packed_transaction(_pending_block_trace->implicit_transactions.back()), get_chain_id(), head_block_time(), optional<time_point>(), true /*is implicit*/);
491
   _push_transaction(std::move(mtrx));
492 493
}

494 495
/**
 *  Wraps up all work for current shards, starts a new cycle, and
496
 *  executes any pending transactions
497
 */
498
void chain_controller::_start_pending_cycle() {
499 500 501 502 503
   // only add a new cycle if there are no cycles or if the previous cycle isn't empty
   if (_pending_block->regions.back().cycles_summary.empty() ||
       (!_pending_block->regions.back().cycles_summary.back().empty() &&
        !_pending_block->regions.back().cycles_summary.back().back().empty()))
      _pending_block->regions.back().cycles_summary.resize( _pending_block->regions[0].cycles_summary.size() + 1 );
504 505


506
   _pending_cycle_trace = cycle_trace();
507 508

   _pending_cycle_trace->shard_traces.resize(_pending_cycle_trace->shard_traces.size() + 1 );
509 510 511 512

   auto& bcycle = _pending_block->regions.back().cycles_summary.back();
   if(bcycle.empty() || !bcycle.back().empty())
      bcycle.resize( bcycle.size()+1 );
B
Bart Wyatt 已提交
513 514
}

515 516
void chain_controller::_finalize_pending_cycle()
{
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
   // prune empty shard
   if (!_pending_block->regions.back().cycles_summary.empty() &&
       !_pending_block->regions.back().cycles_summary.back().empty() &&
       _pending_block->regions.back().cycles_summary.back().back().empty()) {
      _pending_block->regions.back().cycles_summary.back().resize( _pending_block->regions.back().cycles_summary.back().size() - 1 );
      _pending_cycle_trace->shard_traces.resize(_pending_cycle_trace->shard_traces.size() - 1 );
   }
   // prune empty cycle
   if (!_pending_block->regions.back().cycles_summary.empty() &&
       _pending_block->regions.back().cycles_summary.back().empty()) {
      _pending_block->regions.back().cycles_summary.resize( _pending_block->regions.back().cycles_summary.size() - 1 );
      _pending_cycle_trace.reset();
      return;
   }

B
Bart Wyatt 已提交
532 533 534 535 536 537
   for( int idx = 0; idx < _pending_cycle_trace->shard_traces.size(); idx++ ) {
      auto& trace = _pending_cycle_trace->shard_traces.at(idx);
      auto& shard = _pending_block->regions.back().cycles_summary.back().at(idx);

      trace.finalize_shard();
      shard.read_locks.reserve(trace.read_locks.size());
538
      shard.read_locks.insert(shard.read_locks.end(), trace.read_locks.begin(), trace.read_locks.end());
B
Bart Wyatt 已提交
539 540 541

      shard.write_locks.reserve(trace.write_locks.size());
      shard.write_locks.insert(shard.write_locks.end(), trace.write_locks.begin(), trace.write_locks.end());
542 543
   }

544
   _apply_cycle_trace(*_pending_cycle_trace);
545
   _pending_block_trace->region_traces.back().cycle_traces.emplace_back(std::move(*_pending_cycle_trace));
546 547
   _pending_cycle_trace.reset();
}
B
Bart Wyatt 已提交
548

549 550
void chain_controller::_apply_cycle_trace( const cycle_trace& res )
{
551 552 553
   auto &generated_transaction_idx = _db.get_mutable_index<generated_transaction_multi_index>();
   const auto &generated_index = generated_transaction_idx.indices().get<by_sender_id>();

554
   // TODO: Check for conflicts in deferred_transaction_requests between shards
555 556
   for (const auto&st: res.shard_traces) {
      for (const auto &tr: st.transaction_traces) {
557 558 559 560 561
         for (const auto &req: tr.deferred_transaction_requests) {
            if ( req.contains<deferred_transaction>() ) {
               const auto& dt = req.get<deferred_transaction>();
               const auto itr = generated_index.lower_bound(boost::make_tuple(dt.sender, dt.sender_id));
               if ( itr != generated_index.end() && itr->sender == dt.sender && itr->sender_id == dt.sender_id ) {
562
                  _destroy_generated_transaction(*itr);
563
               }
564

565
               _create_generated_transaction(dt);
566 567 568 569
            } else if ( req.contains<deferred_reference>() ) {
               const auto& dr = req.get<deferred_reference>();
               const auto itr = generated_index.lower_bound(boost::make_tuple(dr.sender, dr.sender_id));
               if ( itr != generated_index.end() && itr->sender == dr.sender && itr->sender_id == dr.sender_id ) {
B
Bart Wyatt 已提交
570
                  _destroy_generated_transaction(*itr);
571 572 573
               }
            }
         }
574 575 576 577
         ///TODO: hook this up as a signal handler in a de-coupled "logger" that may just silently drop them
         for (const auto &ar : tr.action_traces) {
            if (!ar.console.empty()) {
               auto prefix = fc::format_string(
578
                  "\n[(${a},${n})->${r}]",
579
                  fc::mutable_variant_object()
B
Bart Wyatt 已提交
580 581
                     ("a", ar.act.account)
                     ("n", ar.act.name)
582
                     ("r", ar.receiver));
583 584 585
               ilog(prefix + ": CONSOLE OUTPUT BEGIN =====================\n"
                    + ar.console
                    + prefix + ": CONSOLE OUTPUT END   =====================" );
586
            }
587
         }
B
Bart Wyatt 已提交
588 589 590 591
      }
   }
}

592 593 594 595
/**
 *  After applying all transactions successfully we can update
 *  the current block time, block number, producer stats, etc
 */
596
void chain_controller::_finalize_block( const block_trace& trace, const producer_object& signing_producer ) { try {
597 598 599 600 601 602 603 604 605
   const auto& b = trace.block;

   update_global_properties( b );
   update_global_dynamic_data( b );
   update_signing_producer(signing_producer, b);

   create_block_summary(b);
   clear_expired_transactions();

606
   update_last_irreversible_block();
607
   _resource_limits.process_account_limit_updates();
608

609 610 611 612 613 614
   const auto& chain_config = this->get_global_properties().configuration;
   _resource_limits.set_block_parameters(
      {EOS_PERCENT(chain_config.max_block_cpu_usage, chain_config.target_block_cpu_usage_pct), chain_config.max_block_cpu_usage, config::block_cpu_usage_average_window_ms / config::block_interval_ms, 1000, {99, 100}, {1000, 999}},
      {EOS_PERCENT(chain_config.max_block_net_usage, chain_config.target_block_net_usage_pct), chain_config.max_block_net_usage, config::block_size_average_window_ms / config::block_interval_ms, 1000, {99, 100}, {1000, 999}}
   );

615 616
   // trigger an update of our elastic values for block limits
   _resource_limits.process_block_usage(b.block_num());
617

618
  // validate_block_header( _skip_flags, b );
619
   applied_block( trace ); //emit
620 621 622 623 624
   if (_currently_replaying_blocks)
     applied_irreversible_block(b);

} FC_CAPTURE_AND_RETHROW( (trace.block) ) }

625
signed_block chain_controller::generate_block(
D
Daniel Larimer 已提交
626 627 628
   block_timestamp_type when,
   account_name producer,
   const private_key_type& block_signing_private_key,
N
Nathan Hourt 已提交
629 630 631
   uint32_t skip /* = 0 */
   )
{ try {
632
   return with_skip_flags( skip | created_block, [&](){
D
Daniel Larimer 已提交
633
      return _db.with_write_lock( [&](){
D
Daniel Larimer 已提交
634
         return _generate_block( when, producer, block_signing_private_key );
D
Daniel Larimer 已提交
635
      });
N
Nathan Hourt 已提交
636
   });
D
Daniel Larimer 已提交
637
} FC_CAPTURE_AND_RETHROW( (when) ) }
N
Nathan Hourt 已提交
638

639 640
signed_block chain_controller::_generate_block( block_timestamp_type when,
                                              account_name producer,
D
Daniel Larimer 已提交
641 642
                                              const private_key_type& block_signing_key )
{ try {
643

644
   try {
645
      FC_ASSERT( head_block_time() < (fc::time_point)when, "block must be generated at a timestamp after the head block time" );
646 647 648 649 650
      uint32_t skip     = _skip_flags;
      uint32_t slot_num = get_slot_at_time( when );
      FC_ASSERT( slot_num > 0 );
      account_name scheduled_producer = get_scheduled_producer( slot_num );
      FC_ASSERT( scheduled_producer == producer );
N
Nathan Hourt 已提交
651

652
      const auto& producer_obj = get_producer(scheduled_producer);
N
Nathan Hourt 已提交
653

654 655 656
      if( !_pending_block ) {
         _start_pending_block();
      }
657

658
      _finalize_pending_cycle();
659

660
      if( !(skip & skip_producer_signature) )
K
Kevin Heifner 已提交
661 662
         FC_ASSERT( producer_obj.signing_key == block_signing_key.get_public_key(),
                    "producer key ${pk}, block key ${bk}", ("pk", producer_obj.signing_key)("bk", block_signing_key.get_public_key()) );
N
Nathan Hourt 已提交
663

B
Brian Johnson 已提交
664 665 666 667
      _pending_block->timestamp   = when;
      _pending_block->producer    = producer_obj.owner;
      _pending_block->previous    = head_block_id();
      _pending_block->block_mroot = get_dynamic_global_properties().block_merkle_root.get_root();
668
      _pending_block->transaction_mroot = _pending_block_trace->calculate_transaction_merkle_root();
B
Brian Johnson 已提交
669
      _pending_block->action_mroot = _pending_block_trace->calculate_action_merkle_root();
S
Spartucus 已提交
670 671

      if( is_start_of_round( _pending_block->block_num() ) ) {
672 673 674 675
         auto latest_producer_schedule = _calculate_producer_schedule();
         if( latest_producer_schedule != _head_producer_schedule() )
            _pending_block->new_producers = latest_producer_schedule;
      }
676
      _pending_block->schedule_version = get_global_properties().active_producers.version;
677

678 679
      if( !(skip & skip_producer_signature) )
         _pending_block->sign( block_signing_key );
680

681
      _finalize_block( *_pending_block_trace, producer_obj );
N
Nathan Hourt 已提交
682

683
      _pending_block_session->push();
D
Daniel Larimer 已提交
684

685
      auto result = move( *_pending_block );
686

687
      clear_pending();
D
Daniel Larimer 已提交
688

689 690 691 692 693
      if (!(skip&skip_fork_db)) {
         _fork_db.push_block(result);
      }
      return result;
   } catch ( ... ) {
694
      clear_pending();
695

696 697 698
      elog( "error while producing block" );
      _start_pending_block();
      throw;
N
Nathan Hourt 已提交
699 700
   }

N
Nathan Hourt 已提交
701
} FC_CAPTURE_AND_RETHROW( (producer) ) }
N
Nathan Hourt 已提交
702 703

/**
N
Nathan Hourt 已提交
704
 * Removes the most recent block from the database and undoes any changes it made.
N
Nathan Hourt 已提交
705
 */
706
void chain_controller::pop_block()
N
Nathan Hourt 已提交
707
{ try {
708
   clear_pending();
N
Nathan Hourt 已提交
709 710
   auto head_id = head_block_id();
   optional<signed_block> head_block = fetch_block_by_id( head_id );
711

N
Nathan Hourt 已提交
712
   EOS_ASSERT( head_block.valid(), pop_empty_chain, "there are no blocks to pop" );
713
   wlog( "\rpop block #${n} from ${pro} ${time}  ${id}", ("n",head_block->block_num())("pro",name(head_block->producer))("time",head_block->timestamp)("id",head_block->id()));
N
Nathan Hourt 已提交
714 715

   _fork_db.pop_block();
716
   _db.undo();
N
Nathan Hourt 已提交
717 718
} FC_CAPTURE_AND_RETHROW() }

719
void chain_controller::clear_pending()
N
Nathan Hourt 已提交
720
{ try {
721
   _pending_block_trace.reset();
D
Daniel Larimer 已提交
722
   _pending_block.reset();
D
Daniel Larimer 已提交
723
   _pending_block_session.reset();
724
   _pending_transaction_metas.clear();
N
Nathan Hourt 已提交
725 726 727 728
} FC_CAPTURE_AND_RETHROW() }

//////////////////// private methods ////////////////////

D
Daniel Larimer 已提交
729
void chain_controller::_apply_block(const signed_block& next_block, uint32_t skip)
N
Nathan Hourt 已提交
730 731
{
   auto block_num = next_block.block_num();
732 733 734 735 736
   if (_checkpoints.size() && _checkpoints.rbegin()->second != block_id_type()) {
      auto itr = _checkpoints.find(block_num);
      if (itr != _checkpoints.end())
         FC_ASSERT(next_block.id() == itr->second,
                   "Block did not match checkpoint", ("checkpoint",*itr)("block_id",next_block.id()));
N
Nathan Hourt 已提交
737

738
      if (_checkpoints.rbegin()->first >= block_num)
N
Nathan Hourt 已提交
739 740
         skip = ~0;// WE CAN SKIP ALMOST EVERYTHING
   }
N
Nathan Hourt 已提交
741 742 743

   with_applying_block([&] {
      with_skip_flags(skip, [&] {
D
Daniel Larimer 已提交
744
         __apply_block(next_block);
N
Nathan Hourt 已提交
745 746
      });
   });
N
Nathan Hourt 已提交
747 748
}

749 750
static void validate_shard_locks(const vector<shard_lock>& locks, const string& tag) {
   if (locks.size() < 2) {
751 752 753
      return;
   }

B
Bart Wyatt 已提交
754
   for (auto cur = locks.begin() + 1; cur != locks.end(); ++cur) {
755
      auto prev = cur - 1;
B
Bart Wyatt 已提交
756 757
      EOS_ASSERT(*prev != *cur, block_lock_exception, "${tag} lock \"${a}::${s}\" is not unique", ("tag",tag)("a",cur->account)("s",cur->scope));
      EOS_ASSERT(*prev < *cur,  block_lock_exception, "${tag} locks are not sorted", ("tag",tag));
758 759
   }
}
760

D
Daniel Larimer 已提交
761
void chain_controller::__apply_block(const signed_block& next_block)
N
Nathan Hourt 已提交
762
{ try {
763 764
   optional<fc::time_point> processing_deadline;
   if (!_currently_replaying_blocks && _limits.max_push_block_us.count() > 0) {
B
Bart Wyatt 已提交
765
      processing_deadline = fc::time_point::now() + _limits.max_push_block_us;
766 767
   }

N
Nathan Hourt 已提交
768
   uint32_t skip = _skip_flags;
N
Nathan Hourt 已提交
769

770 771
   const producer_object& signing_producer = validate_block_header(skip, next_block);

772 773 774 775
   /// regions must be listed in order
   for( uint32_t i = 1; i < next_block.regions.size(); ++i )
      FC_ASSERT( next_block.regions[i-1].region < next_block.regions[i].region );

776
   block_trace next_block_trace(next_block);
777

B
Bucky Kittinger 已提交
778
   /// cache the input transaction ids so that they can be looked up when executing the
779
   /// summary
780
   vector<transaction_metadata> input_metas;
B
Bucky Kittinger 已提交
781
   // add all implicit transactions
782
   {
783
      next_block_trace.implicit_transactions.emplace_back(_get_on_block_transaction());
784
   }
B
Bucky Kittinger 已提交
785 786

   input_metas.reserve(next_block.input_transactions.size() + next_block_trace.implicit_transactions.size());
787

B
Bucky Kittinger 已提交
788
   for ( const auto& t : next_block_trace.implicit_transactions ) {
789
      input_metas.emplace_back(packed_transaction(t), get_chain_id(), head_block_time(), processing_deadline, true /*implicit*/);
B
Bucky Kittinger 已提交
790 791
   }

B
Bart Wyatt 已提交
792
   map<transaction_id_type,size_t> trx_index;
793
   for( const auto& t : next_block.input_transactions ) {
794
      input_metas.emplace_back(t, chain_id_type(), next_block.timestamp, processing_deadline);
795 796 797 798 799
      validate_transaction_with_minimal_state( input_metas.back().trx(), input_metas.back().billable_packed_size );
      if( should_check_signatures() ) {
         input_metas.back().signing_keys = input_metas.back().trx().get_signature_keys( t.signatures, chain_id_type(),
                                                                                        input_metas.back().context_free_data, false );
      }
B
Bart Wyatt 已提交
800
      trx_index[input_metas.back().id] =  input_metas.size() - 1;
801
   }
802

803 804
   next_block_trace.region_traces.reserve(next_block.regions.size());

805 806
   for( uint32_t region_index = 0; region_index < next_block.regions.size(); ++region_index ) {
      const auto& r = next_block.regions[region_index];
807 808 809
      region_trace r_trace;
      r_trace.cycle_traces.reserve(r.cycles_summary.size());

810
      EOS_ASSERT(!r.cycles_summary.empty(), tx_empty_region,"region[${r_index}] has no cycles", ("r_index",region_index));
811
      for (uint32_t cycle_index = 0; cycle_index < r.cycles_summary.size(); cycle_index++) {
812
         const auto& cycle = r.cycles_summary.at(cycle_index);
813 814 815
         cycle_trace c_trace;
         c_trace.shard_traces.reserve(cycle.size());

816 817
         // validate that no read_scope is used as a write scope in this cycle and that no two shards
         // share write scopes
818 819
         set<shard_lock> read_locks;
         map<shard_lock, uint32_t> write_locks;
820

821
         EOS_ASSERT(!cycle.empty(), tx_empty_cycle,"region[${r_index}] cycle[${c_index}] has no shards", ("r_index",region_index)("c_index",cycle_index));
822 823
         for (uint32_t shard_index = 0; shard_index < cycle.size(); shard_index++) {
            const auto& shard = cycle.at(shard_index);
824 825
            EOS_ASSERT(!shard.empty(), tx_empty_shard,"region[${r_index}] cycle[${c_index}] shard[${s_index}] is empty",
                       ("r_index",region_index)("c_index",cycle_index)("s_index",shard_index));
826

827
            // Validate that the shards locks are unique and sorted
828 829 830 831
            validate_shard_locks(shard.read_locks,  "read");
            validate_shard_locks(shard.write_locks, "write");

            for (const auto& s: shard.read_locks) {
B
Bart Wyatt 已提交
832
               EOS_ASSERT(write_locks.count(s) == 0, block_concurrency_exception,
833 834 835
                  "shard ${i} requires read lock \"${a}::${s}\" which is locked for write by shard ${j}",
                  ("i", shard_index)("s", s)("j", write_locks[s]));
               read_locks.emplace(s);
836 837
            }

838
            for (const auto& s: shard.write_locks) {
B
Bart Wyatt 已提交
839
               EOS_ASSERT(write_locks.count(s) == 0, block_concurrency_exception,
840
                  "shard ${i} requires write lock \"${a}::${s}\" which is locked for write by shard ${j}",
B
Bart Wyatt 已提交
841 842 843 844
                  ("i", shard_index)("a", s.account)("s", s.scope)("j", write_locks[s]));
               EOS_ASSERT(read_locks.count(s) == 0, block_concurrency_exception,
                  "shard ${i} requires write lock \"${a}::${s}\" which is locked for read",
                  ("i", shard_index)("a", s.account)("s", s.scope));
845
               write_locks[s] = shard_index;
846 847
            }

B
Bart Wyatt 已提交
848 849
            flat_set<shard_lock> used_read_locks;
            flat_set<shard_lock> used_write_locks;
B
Bart Wyatt 已提交
850

851
            shard_trace s_trace;
B
Bart Wyatt 已提交
852
            for (const auto& receipt : shard.transactions) {
853 854
                optional<transaction_metadata> _temp;
                auto make_metadata = [&]() -> transaction_metadata* {
855 856
                  auto itr = trx_index.find(receipt.id);
                  if( itr != trx_index.end() ) {
857
                     auto& trx_meta = input_metas.at(itr->second);
858 859 860 861
                     const auto& trx = trx_meta.trx();
                     trx_meta.delay = fc::seconds(trx.delay_sec);

                     validate_expiration_not_too_far(trx, head_block_time() + trx_meta.delay);
862
                     validate_referenced_accounts(trx);
863
                     validate_uniqueness(trx);
864 865 866 867 868 869 870 871 872 873 874
                     if( should_check_authorization() ) {
                        FC_ASSERT( !should_check_signatures() || trx_meta.signing_keys,
                                   "signing_keys missing from transaction_metadata of an input transaction" );
                        auto enforced_delay = check_authorization( trx.actions,
                                                                   should_check_signatures() ? *trx_meta.signing_keys
                                                                                             : flat_set<public_key_type>() );
                        EOS_ASSERT( trx_meta.delay >= enforced_delay,
                                    transaction_exception,
                                    "authorization imposes a delay (${enforced_delay} sec) greater than the delay specified in transaction header (${specified_delay} sec)",
                                    ("enforced_delay", enforced_delay.to_seconds())("specified_delay", trx_meta.delay.to_seconds()) );
                     }
875

B
Bart Wyatt 已提交
876
                     return &input_metas.at(itr->second);
B
Bart Wyatt 已提交
877
                  } else {
878 879
                     const auto* gtrx = _db.find<generated_transaction_object,by_trx_id>(receipt.id);
                     if (gtrx != nullptr) {
880
                        //ilog( "defer" );
881
                        auto trx = fc::raw::unpack<deferred_transaction>(gtrx->packed_trx.data(), gtrx->packed_trx.size());
882
                        FC_ASSERT( trx.execute_after <= head_block_time() , "deferred transaction executed prematurely" );
883 884
                        validate_not_expired( trx );
                        validate_uniqueness( trx );
885
                        _temp.emplace(trx, gtrx->published, trx.sender, trx.sender_id, gtrx->packed_trx.data(), gtrx->packed_trx.size(), processing_deadline );
886
                        _destroy_generated_transaction(*gtrx);
887 888
                        return &*_temp;
                     } else {
889
                        //ilog( "implicit" );
B
Bucky Kittinger 已提交
890 891 892 893 894
                        for ( size_t i=0; i < next_block_trace.implicit_transactions.size(); i++ ) {
                           if ( input_metas[i].id == receipt.id )
                              return &input_metas[i];
                        }
                        FC_ASSERT(false, "implicit transaction not found ${trx}", ("trx", receipt));
895
                     }
896
                  }
897
               };
B
Bart Wyatt 已提交
898

899
               auto *mtrx = make_metadata();
900

901 902
               FC_ASSERT( mtrx->trx().region == r.region, "transaction was scheduled into wrong region" );

903 904 905 906 907
               mtrx->region_id = r.region;
               mtrx->cycle_index = cycle_index;
               mtrx->shard_index = shard_index;
               mtrx->allowed_read_locks.emplace(&shard.read_locks);
               mtrx->allowed_write_locks.emplace(&shard.write_locks);
B
Bart Wyatt 已提交
908

909 910 911 912 913 914
               if( mtrx->delay.count() == 0 ) {
                  s_trace.transaction_traces.emplace_back(_apply_transaction(*mtrx));
                  record_locks_for_data_access(s_trace.transaction_traces.back(), used_read_locks, used_write_locks);
               } else {
                  s_trace.transaction_traces.emplace_back(delayed_transaction_processing(*mtrx));
               }
915 916

               auto& t_trace = s_trace.transaction_traces.back();
917
               if( mtrx->raw_trx.valid() && !mtrx->is_implicit ) { // if an input transaction
918
                  t_trace.packed_trx_digest = mtrx->packed_digest;
919
               }
920 921 922
               t_trace.region_id = r.region;
               t_trace.cycle_index = cycle_index;
               t_trace.shard_index = shard_index;
923

924 925 926
               EOS_ASSERT( receipt.status == s_trace.transaction_traces.back().status, tx_receipt_inconsistent_status,
                           "Received status of transaction from block (${rstatus}) does not match the applied transaction's status (${astatus})",
                           ("rstatus",receipt.status)("astatus",s_trace.transaction_traces.back().status) );
927 928 929 930 931 932
               EOS_ASSERT( receipt.kcpu_usage == s_trace.transaction_traces.back().kcpu_usage, tx_receipt_inconsistent_cpu,
                           "Received kcpu_usage of transaction from block (${rcpu}) does not match the applied transaction's kcpu_usage (${acpu})",
                           ("rcpu",receipt.kcpu_usage)("acpu",s_trace.transaction_traces.back().kcpu_usage) );
               EOS_ASSERT( receipt.net_usage_words == s_trace.transaction_traces.back().net_usage_words, tx_receipt_inconsistent_net,
                           "Received net_usage_words of transaction from block (${rnet}) does not match the applied transaction's net_usage_words (${anet})",
                           ("rnet",receipt.net_usage_words)("anet",s_trace.transaction_traces.back().net_usage_words) );
B
Bart Wyatt 已提交
933

934
            } /// for each transaction id
N
Nathan Hourt 已提交
935

936
            EOS_ASSERT( boost::equal( used_read_locks, shard.read_locks ),
B
Bart Wyatt 已提交
937
               block_lock_exception, "Read locks for executing shard: ${s} do not match those listed in the block", ("s", shard_index));
938
            EOS_ASSERT( boost::equal( used_write_locks, shard.write_locks ),
B
Bart Wyatt 已提交
939 940
               block_lock_exception, "Write locks for executing shard: ${s} do not match those listed in the block", ("s", shard_index));

941
            s_trace.finalize_shard();
942 943
            c_trace.shard_traces.emplace_back(move(s_trace));
         } /// for each shard
D
Daniel Larimer 已提交
944

945
         _resource_limits.synchronize_account_ram_usage();
946 947 948
         _apply_cycle_trace(c_trace);
         r_trace.cycle_traces.emplace_back(move(c_trace));
      } /// for each cycle
D
Daniel Larimer 已提交
949

950 951
      next_block_trace.region_traces.emplace_back(move(r_trace));
   } /// for each region
N
Nathan Hourt 已提交
952

953 954
   FC_ASSERT( next_block.action_mroot == next_block_trace.calculate_action_merkle_root(), "action merkle root does not match");
   FC_ASSERT( next_block.transaction_mroot == next_block_trace.calculate_transaction_merkle_root(), "transaction merkle root does not match" );
N
Nathan Hourt 已提交
955

956
   _finalize_block( next_block_trace, signing_producer );
957
} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) )  }
D
Daniel Larimer 已提交
958

959 960
flat_set<public_key_type> chain_controller::get_required_keys(const transaction& trx,
                                                              const flat_set<public_key_type>& candidate_keys)const
D
Daniel Larimer 已提交
961
{
962
   auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; },
963
                                     noop_permission_visitor(),
964 965
                                     get_global_properties().configuration.max_authority_depth,
                                     candidate_keys);
966

967
   for (const auto& act : trx.actions ) {
D
Daniel Larimer 已提交
968 969 970
      for (const auto& declared_auth : act.authorization) {
         if (!checker.satisfied(declared_auth)) {
            EOS_ASSERT(checker.satisfied(declared_auth), tx_missing_sigs,
D
Daniel Larimer 已提交
971
                       "transaction declares authority '${auth}', but does not have signatures for it.",
D
Daniel Larimer 已提交
972
                       ("auth", declared_auth));
973 974 975 976 977 978 979
         }
      }
   }

   return checker.used_keys();
}

M
Matias Romeo 已提交
980

981 982
class permission_visitor {
public:
983 984 985 986
   permission_visitor(const chain_controller& controller)
   : _chain_controller(controller) {
      _max_delay_stack.emplace_back();
   }
987 988 989

   void operator()(const permission_level& perm_level) {
      const auto obj = _chain_controller.get_permission(perm_level);
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
      if( _max_delay_stack.back() < obj.delay )
         _max_delay_stack.back() = obj.delay;
   }

   void push_undo() {
      _max_delay_stack.emplace_back( _max_delay_stack.back() );
   }

   void pop_undo() {
      FC_ASSERT( _max_delay_stack.size() >= 2, "invariant failure in permission_visitor" );
      _max_delay_stack.pop_back();
   }

   void squash_undo() {
      FC_ASSERT( _max_delay_stack.size() >= 2, "invariant failure in permission_visitor" );
      auto delay_to_keep = _max_delay_stack.back();
      _max_delay_stack.pop_back();
      _max_delay_stack.back() = delay_to_keep;
   }

   fc::microseconds get_max_delay() const {
      FC_ASSERT( _max_delay_stack.size() == 1, "invariant failure in permission_visitor" );
      return _max_delay_stack.back();
1013 1014 1015 1016
   }

private:
   const chain_controller& _chain_controller;
1017
   vector<fc::microseconds> _max_delay_stack;
1018 1019
};

1020 1021 1022
fc::microseconds chain_controller::check_authorization( const vector<action>& actions,
                                                        const flat_set<public_key_type>& provided_keys,
                                                        bool allow_unused_signatures,
1023 1024
                                                        flat_set<account_name> provided_accounts,
                                                        flat_set<permission_level> provided_levels)const
D
Daniel Larimer 已提交
1025
{
1026
   auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; },
1027
                                     permission_visitor(*this),
1028
                                     get_global_properties().configuration.max_authority_depth,
1029
                                     provided_keys, provided_accounts, provided_levels );
1030

1031
   fc::microseconds max_delay;
N
Nathan Hourt 已提交
1032

1033
   for( const auto& act : actions ) {
1034
      for( const auto& declared_auth : act.authorization ) {
D
Daniel Larimer 已提交
1035

1036
         // check a minimum permission if one is set, otherwise assume the contract code will validate
B
Bart Wyatt 已提交
1037
         auto min_permission_name = lookup_minimum_permission(declared_auth.actor, act.account, act.name);
1038
         if( !min_permission_name ) {
1039
            // for updateauth actions, need to determine the permission that is changing
1040
            if( act.account == config::system_account_name && act.name == contracts::updateauth::get_name() ) {
1041 1042
               auto update = act.data_as<contracts::updateauth>();
               const auto permission_to_change = _db.find<permission_object, by_owner>(boost::make_tuple(update.account, update.permission));
1043 1044
               if( permission_to_change != nullptr ) {
                  // Only changes to permissions need to possibly be delayed. New permissions can be added immediately.
1045 1046 1047 1048
                  min_permission_name = update.permission;
               }
            }
         }
1049
         if( min_permission_name ) {
1050
            const auto& min_permission = _db.get<permission_object, by_owner>(boost::make_tuple(declared_auth.actor, *min_permission_name));
1051 1052 1053 1054 1055 1056 1057 1058
            const auto& index = _db.get_index<permission_index>().indices();
            const optional<fc::microseconds> delay = get_permission(declared_auth).satisfies(min_permission, index);
            EOS_ASSERT( delay.valid(),
                        tx_irrelevant_auth,
                        "action declares irrelevant authority '${auth}'; minimum authority is ${min}",
                        ("auth", declared_auth)("min", min_permission.name) );
            if( max_delay < *delay )
               max_delay = *delay;
N
Nathan Hourt 已提交
1059
         }
1060

1061
         if( act.account == config::system_account_name ) {
1062 1063
            // for link changes, we need to also determine the delay associated with an existing link that is being
            // moved or removed
1064
            if( act.name == contracts::linkauth::get_name() ) {
1065
               auto link = act.data_as<contracts::linkauth>();
1066
               if( declared_auth.actor == link.account ) {
1067
                  const auto linked_permission_name = lookup_linked_permission(link.account, link.code, link.type);
1068
                  if( linked_permission_name.valid() && *linked_permission_name != config::eosio_any_name ) {
1069 1070
                     const auto& linked_permission = _db.get<permission_object, by_owner>(boost::make_tuple(link.account, *linked_permission_name));
                     const auto& index = _db.get_index<permission_index>().indices();
1071 1072
                     const optional<fc::microseconds> delay = get_permission(declared_auth).satisfies(linked_permission, index);
                     if( delay.valid() && max_delay < *delay )
1073 1074 1075
                        max_delay = *delay;
                  } // else it is only a new link, so don't need to delay
               }
1076
            } else if( act.name == contracts::unlinkauth::get_name() ) {
1077
               auto unlink = act.data_as<contracts::unlinkauth>();
1078
               if( declared_auth.actor == unlink.account ) {
1079
                  const auto unlinked_permission_name = lookup_linked_permission(unlink.account, unlink.code, unlink.type);
1080
                  if( unlinked_permission_name.valid() && *unlinked_permission_name != config::eosio_any_name ) {
1081 1082
                     const auto& unlinked_permission = _db.get<permission_object, by_owner>(boost::make_tuple(unlink.account, *unlinked_permission_name));
                     const auto& index = _db.get_index<permission_index>().indices();
1083 1084
                     const optional<fc::microseconds> delay = get_permission(declared_auth).satisfies(unlinked_permission, index);
                     if( delay.valid() && max_delay < *delay )
1085 1086 1087 1088 1089 1090
                        max_delay = *delay;
                  }
               }
            }
         }

1091
         if( should_check_signatures() ) {
D
Daniel Larimer 已提交
1092
            EOS_ASSERT(checker.satisfied(declared_auth), tx_missing_sigs,
D
Daniel Larimer 已提交
1093
                       "transaction declares authority '${auth}', but does not have signatures for it.",
D
Daniel Larimer 已提交
1094
                       ("auth", declared_auth));
N
Nathan Hourt 已提交
1095 1096
         }
      }
1097
   }
N
Nathan Hourt 已提交
1098

1099 1100 1101 1102 1103
   if( !allow_unused_signatures && should_check_signatures() ) {
      EOS_ASSERT( checker.all_keys_used(), tx_irrelevant_sig,
                  "transaction bears irrelevant signatures from these keys: ${keys}",
                  ("keys", checker.unused_keys()) );
   }
1104 1105

   const auto checker_max_delay = checker.get_permission_visitor().get_max_delay();
1106
   if( max_delay < checker_max_delay )
1107 1108 1109
      max_delay = checker_max_delay;

   return max_delay;
N
Nathan Hourt 已提交
1110 1111
}

M
Matias Romeo 已提交
1112 1113 1114 1115 1116
bool chain_controller::check_authorization( account_name account, permission_name permission,
                                         flat_set<public_key_type> provided_keys,
                                         bool allow_unused_signatures)const
{
   auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; },
1117 1118 1119
                                     noop_permission_visitor(),
                                     get_global_properties().configuration.max_authority_depth,
                                     provided_keys);
M
Matias Romeo 已提交
1120 1121 1122

   auto satisfied = checker.satisfied({account, permission});

1123
   if( satisfied && !allow_unused_signatures ) {
M
Matias Romeo 已提交
1124 1125 1126 1127 1128 1129 1130 1131
      EOS_ASSERT(checker.all_keys_used(), tx_irrelevant_sig,
                 "irrelevant signatures from these keys: ${keys}",
                 ("keys", checker.unused_keys()));
   }

   return satisfied;
}

1132 1133 1134 1135
fc::microseconds chain_controller::check_transaction_authorization(const transaction& trx,
                                                                   const vector<signature_type>& signatures,
                                                                   const vector<bytes>& cfd,
                                                                   bool allow_unused_signatures)const
1136
{
1137
   if( should_check_signatures() ) {
1138
      return check_authorization( trx.actions,
1139 1140
                                  trx.get_signature_keys( signatures, chain_id_type{}, cfd, allow_unused_signatures ),
                                  allow_unused_signatures );
1141
   } else {
1142
      return check_authorization( trx.actions, flat_set<public_key_type>(), true );
1143
   }
1144 1145
}

1146
optional<permission_name> chain_controller::lookup_minimum_permission(account_name authorizer_account,
D
Daniel Larimer 已提交
1147 1148
                                                                    account_name scope,
                                                                    action_name act_name) const {
1149
#warning TODO: this comment sounds like it is expecting a check ("may") somewhere else, but I have not found anything else
1150 1151
   // updateauth is a special case where any permission _may_ be suitable depending
   // on the contents of the action
1152
   if( scope == config::system_account_name && act_name == contracts::updateauth::get_name() ) {
1153 1154 1155
      return optional<permission_name>();
   }

1156 1157
   try {
      optional<permission_name> linked_permission = lookup_linked_permission(authorizer_account, scope, act_name);
1158
      if( !linked_permission )
1159 1160
         return config::active_name;

1161
      if( *linked_permission == config::eosio_any_name )
1162 1163
         return optional<permission_name>();

1164 1165 1166 1167 1168 1169 1170
      return linked_permission;
   } FC_CAPTURE_AND_RETHROW((authorizer_account)(scope)(act_name))
}

optional<permission_name> chain_controller::lookup_linked_permission(account_name authorizer_account,
                                                                     account_name scope,
                                                                     action_name act_name) const {
N
Nathan Hourt 已提交
1171
   try {
D
Daniel Larimer 已提交
1172 1173 1174
      // First look up a specific link for this message act_name
      auto key = boost::make_tuple(authorizer_account, scope, act_name);
      auto link = _db.find<permission_link_object, by_action_name>(key);
1175 1176 1177
      // If no specific link found, check for a contract-wide default
      if (link == nullptr) {
         get<2>(key) = "";
D
Daniel Larimer 已提交
1178
         link = _db.find<permission_link_object, by_action_name>(key);
1179 1180 1181
      }

      // If no specific or default link found, use active permission
D
Daniel Larimer 已提交
1182
      if (link != nullptr) {
1183
         return link->required_permission;
1184 1185
      }
      return optional<permission_name>();
D
Daniel Larimer 已提交
1186 1187

    //  return optional<permission_name>();
D
Daniel Larimer 已提交
1188
   } FC_CAPTURE_AND_RETHROW((authorizer_account)(scope)(act_name))
N
Nathan Hourt 已提交
1189 1190
}

1191
void chain_controller::validate_uniqueness( const transaction& trx )const {
N
Nathan Hourt 已提交
1192
   if( !should_check_for_duplicate_transactions() ) return;
1193
   auto transaction = _db.find<transaction_object, by_trx_id>(trx.id());
1194
   EOS_ASSERT(transaction == nullptr, tx_duplicate, "Transaction is not unique");
1195
}
1196

1197 1198
void chain_controller::record_transaction(const transaction& trx)
{
1199 1200 1201 1202 1203 1204 1205
   try {
       _db.create<transaction_object>([&](transaction_object& transaction) {
           transaction.trx_id = trx.id();
           transaction.expiration = trx.expiration;
       });
   } catch ( ... ) {
       EOS_ASSERT( false, transaction_exception,
1206
                  "duplicate transaction ${id}",
1207 1208
                  ("id", trx.id() ) );
   }
1209
}
1210

B
Bart Wyatt 已提交
1211 1212
static uint32_t calculate_transaction_cpu_usage( const transaction_trace& trace, const transaction_metadata& meta, const chain_config& chain_configuration ) {
   // calculate the sum of all actions retired
1213
   uint32_t action_cpu_usage = 0;
1214
   uint32_t context_free_actual_cpu_usage = 0;
1215
   for (const auto &at: trace.action_traces) {
1216 1217 1218 1219 1220 1221 1222 1223 1224
      if (at.context_free) {
         context_free_actual_cpu_usage += chain_configuration.base_per_action_cpu_usage + at.cpu_usage;
      } else {
         action_cpu_usage += chain_configuration.base_per_action_cpu_usage + at.cpu_usage;
         if (at.receiver == config::system_account_name &&
             at.act.account == config::system_account_name &&
             at.act.name == N(setcode)) {
            action_cpu_usage += chain_configuration.base_setcode_cpu_usage;
         }
1225 1226 1227 1228
      }
   }

   // charge a system controlled amount for signature verification/recovery
B
Bart Wyatt 已提交
1229
   uint32_t signature_cpu_usage = 0;
1230 1231
   if( meta.signature_count ) {
      signature_cpu_usage = meta.signature_count * chain_configuration.per_signature_cpu_usage;
1232 1233
   }

1234
   uint32_t context_free_cpu_usage = (uint32_t)((uint64_t)context_free_actual_cpu_usage * chain_configuration.context_free_discount_cpu_usage_num / chain_configuration.context_free_discount_cpu_usage_den);
B
Bart Wyatt 已提交
1235

1236 1237 1238 1239
   auto actual_cpu_usage = chain_configuration.base_per_transaction_cpu_usage +
                           action_cpu_usage +
                           context_free_cpu_usage +
                           signature_cpu_usage;
1240
   actual_cpu_usage = ((actual_cpu_usage + 1023)/1024) * 1024; // Round up to nearest multiple of 1024
1241

1242
   uint32_t cpu_usage_limit = meta.trx().max_kcpu_usage.value * 1024UL; // overflow checked in validate_transaction_without_state
1243 1244 1245
   EOS_ASSERT( cpu_usage_limit == 0 || actual_cpu_usage <= cpu_usage_limit, tx_resource_exhausted,
               "declared cpu usage limit of transaction is too low: ${actual_cpu_usage} > ${declared_limit}",
               ("actual_cpu_usage", actual_cpu_usage)("declared_limit",cpu_usage_limit) );
1246

1247
   return actual_cpu_usage;
B
Bart Wyatt 已提交
1248 1249
}

1250
static uint32_t calculate_transaction_net_usage( const transaction_trace& trace, const transaction_metadata& meta, const chain_config& chain_configuration ) {
B
Bart Wyatt 已提交
1251 1252 1253
   // charge a system controlled per-lock overhead to account for shard bloat
   uint32_t lock_net_usage = uint32_t(trace.read_locks.size() + trace.write_locks.size()) * chain_configuration.per_lock_net_usage;

1254 1255 1256
   auto actual_net_usage = chain_configuration.base_per_transaction_net_usage +
                           meta.billable_packed_size +
                           lock_net_usage;
1257
   actual_net_usage = ((actual_net_usage + 7)/8) * 8; // Round up to nearest multiple of 8
1258 1259


1260
   uint32_t net_usage_limit = meta.trx().max_net_usage_words.value * 8UL; // overflow checked in validate_transaction_without_state
1261 1262 1263 1264 1265
   EOS_ASSERT( net_usage_limit == 0 || actual_net_usage <= net_usage_limit, tx_resource_exhausted,
               "declared net usage limit of transaction is too low: ${actual_net_usage} > ${declared_limit}",
               ("actual_net_usage", actual_net_usage)("declared_limit",net_usage_limit) );

   return actual_net_usage;
B
Bart Wyatt 已提交
1266 1267 1268 1269 1270 1271
}

void chain_controller::update_resource_usage( transaction_trace& trace, const transaction_metadata& meta ) {
   const auto& chain_configuration = get_global_properties().configuration;

   trace.cpu_usage = calculate_transaction_cpu_usage(trace, meta, chain_configuration);
1272
   trace.net_usage = calculate_transaction_net_usage(trace, meta, chain_configuration);
1273 1274
   trace.kcpu_usage      = trace.cpu_usage / 1024;
   trace.net_usage_words = trace.net_usage / 8;
B
Bart Wyatt 已提交
1275 1276 1277 1278

   // enforce that the system controlled per tx limits are not violated
   EOS_ASSERT(trace.cpu_usage <= chain_configuration.max_transaction_cpu_usage,
              tx_resource_exhausted, "Transaction exceeds the maximum cpu usage [used: ${used}, max: ${max}]",
1279
              ("used", trace.cpu_usage)("max", chain_configuration.max_transaction_cpu_usage));
B
Bart Wyatt 已提交
1280 1281 1282

   EOS_ASSERT(trace.net_usage <= chain_configuration.max_transaction_net_usage,
              tx_resource_exhausted, "Transaction exceeds the maximum net usage [used: ${used}, max: ${max}]",
1283
              ("used", trace.net_usage)("max", chain_configuration.max_transaction_net_usage));
B
Bart Wyatt 已提交
1284

1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
   // determine the accounts to bill
   set<std::pair<account_name, permission_name>> authorizations;
   for( const auto& act : meta.trx().actions )
      for( const auto& auth : act.authorization )
         authorizations.emplace( auth.actor, auth.permission );


   vector<account_name> bill_to_accounts;
   bill_to_accounts.reserve(authorizations.size());
   for( const auto& ap : authorizations ) {
1295
      bill_to_accounts.push_back(ap.first);
1296 1297
   }

1298 1299 1300
   // for account usage, the ordinal is based on possible blocks not actual blocks.  This means that as blocks are
   // skipped account usage will still decay.
   uint32_t ordinal = (uint32_t)(head_block_time().time_since_epoch().count() / fc::milliseconds(config::block_interval_ms).count());
1301
   _resource_limits.add_transaction_usage(bill_to_accounts, trace.cpu_usage, trace.net_usage, ordinal);
1302 1303
}

1304

D
Daniel Larimer 已提交
1305
void chain_controller::validate_tapos(const transaction& trx)const {
N
Nathan Hourt 已提交
1306
   if (!should_check_tapos()) return;
1307

D
Daniel Larimer 已提交
1308
   const auto& tapos_block_summary = _db.get<block_summary_object>((uint16_t)trx.ref_block_num);
1309 1310

   //Verify TaPoS block summary has correct ID prefix, and that this block's time is not past the expiration
1311 1312
   EOS_ASSERT(trx.verify_reference_block(tapos_block_summary.block_id), invalid_ref_block_exception,
              "Transaction's reference block did not match. Is this transaction from a different fork?",
N
Nathan Hourt 已提交
1313 1314
              ("tapos_summary", tapos_block_summary));
}
1315

1316 1317
void chain_controller::validate_referenced_accounts( const transaction& trx )const
{ try {
D
Daniel Larimer 已提交
1318
   for( const auto& act : trx.actions ) {
B
Bart Wyatt 已提交
1319
      require_account(act.account);
D
Daniel Larimer 已提交
1320
      for (const auto& auth : act.authorization )
D
Daniel Larimer 已提交
1321
         require_account(auth.actor);
1322
   }
D
Daniel Larimer 已提交
1323
} FC_CAPTURE_AND_RETHROW() }
D
Daniel Larimer 已提交
1324

1325 1326 1327 1328
void chain_controller::validate_not_expired( const transaction& trx )const
{ try {
   fc::time_point now = head_block_time();

1329
   EOS_ASSERT( now < time_point(trx.expiration),
1330 1331
               expired_tx_exception,
               "Transaction is expired, now is ${now}, expiration is ${trx.exp}",
1332
               ("now",now)("trx.expiration",trx.expiration) );
1333 1334 1335
} FC_CAPTURE_AND_RETHROW((trx)) }

void chain_controller::validate_expiration_not_too_far( const transaction& trx, fc::time_point reference_time )const
1336
{ try {
D
Daniel Larimer 已提交
1337
   const auto& chain_configuration = get_global_properties().configuration;
1338

1339 1340
   EOS_ASSERT( time_point(trx.expiration) <= reference_time + fc::seconds(chain_configuration.max_transaction_lifetime),
               tx_exp_too_far_exception,
1341 1342 1343 1344
               "Transaction expiration is too far in the future relative to the reference time of ${reference_time}, "
               "expiration is ${trx.expiration} and the maximum transaction lifetime is ${max_til_exp} seconds",
               ("trx.expiration",trx.expiration)("reference_time",reference_time)
               ("max_til_exp",chain_configuration.max_transaction_lifetime) );
1345 1346 1347
} FC_CAPTURE_AND_RETHROW((trx)) }


1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
void chain_controller::validate_transaction_without_state( const transaction& trx )const
{ try {
   EOS_ASSERT( !trx.actions.empty(), tx_no_action, "transaction must have at least one action" );

   // Check for at least one authorization in the context-aware actions
   bool has_auth = false;
   for( const auto& act : trx.actions ) {
      has_auth |= !act.authorization.empty();
      if( has_auth ) break;
   }
   EOS_ASSERT( has_auth, tx_no_auths, "transaction must have at least one authorization" );

   // Check that there are no authorizations in any of the context-free actions
   for (const auto &act : trx.context_free_actions) {
      EOS_ASSERT( act.authorization.empty(), cfa_irrelevant_auth, "context-free actions cannot require authorization" );
   }
1364

1365 1366
   EOS_ASSERT( trx.max_kcpu_usage.value < UINT32_MAX / 1024UL, transaction_exception, "declared max_kcpu_usage overflows when expanded to max cpu usage" );
   EOS_ASSERT( trx.max_net_usage_words.value < UINT32_MAX / 8UL, transaction_exception, "declared max_net_usage_words overflows when expanded to max net usage" );
1367

1368
} FC_CAPTURE_AND_RETHROW((trx)) }
1369

1370
void chain_controller::validate_transaction_with_minimal_state( const transaction& trx, uint32_t min_net_usage )const
1371
{ try {
1372
   validate_transaction_without_state(trx);
1373 1374
   validate_not_expired(trx);
   validate_tapos(trx);
1375

1376 1377 1378 1379 1380
   uint32_t net_usage_limit = trx.max_net_usage_words.value * 8; // overflow checked in validate_transaction_without_state
   EOS_ASSERT( net_usage_limit == 0 || min_net_usage <= net_usage_limit,
               transaction_exception,
               "Packed transaction and associated data does not fit into the space committed to by the transaction's header! [usage=${usage},commitment=${commit}]",
               ("usage", min_net_usage)("commit", net_usage_limit));
1381

1382
} FC_CAPTURE_AND_RETHROW((trx)) }
1383

1384 1385
void chain_controller::require_scope( const scope_name& scope )const {
   switch( uint64_t(scope) ) {
1386 1387
      case config::eosio_all_scope:
      case config::eosio_auth_scope:
1388 1389 1390 1391 1392 1393
         return; /// built in scopes
      default:
         require_account(scope);
   }
}

D
Daniel Larimer 已提交
1394
void chain_controller::require_account(const account_name& name) const {
N
Nathan Hourt 已提交
1395 1396 1397
   auto account = _db.find<account_object, by_name>(name);
   FC_ASSERT(account != nullptr, "Account not found: ${name}", ("name", name));
}
N
Nathan Hourt 已提交
1398

1399
const producer_object& chain_controller::validate_block_header(uint32_t skip, const signed_block& next_block)const { try {
1400 1401
   EOS_ASSERT(head_block_id() == next_block.previous, block_validate_exception, "",
              ("head_block_id",head_block_id())("next.prev",next_block.previous));
D
Daniel Larimer 已提交
1402
   EOS_ASSERT(head_block_time() < (fc::time_point)next_block.timestamp, block_validate_exception, "",
1403
              ("head_block_time",head_block_time())("next",next_block.timestamp)("blocknum",next_block.block_num()));
K
Kevin Heifner 已提交
1404
   if (((fc::time_point)next_block.timestamp) > head_block_time() + fc::microseconds(config::block_interval_ms*1000)) {
1405
      elog("head_block_time ${h}, next_block ${t}, block_interval ${bi}",
1406 1407 1408
           ("h", head_block_time())("t", next_block.timestamp)("bi", config::block_interval_ms));
      elog("Did not produce block within block_interval ${bi}ms, took ${t}ms)",
           ("bi", config::block_interval_ms)("t", (time_point(next_block.timestamp) - head_block_time()).count() / 1000));
1409
   }
1410

1411

1412
   if( !is_start_of_round( next_block.block_num() ) )  {
D
Daniel Larimer 已提交
1413
      EOS_ASSERT(!next_block.new_producers, block_validate_exception,
1414
                 "Producer changes may only occur at the end of a round.");
N
Nathan Hourt 已提交
1415
   }
1416

D
Daniel Larimer 已提交
1417
   const producer_object& producer = get_producer(get_scheduled_producer(get_slot_at_time(next_block.timestamp)));
N
Nathan Hourt 已提交
1418

N
Nathan Hourt 已提交
1419
   if(!(skip&skip_producer_signature))
1420 1421 1422
      EOS_ASSERT(next_block.validate_signee(producer.signing_key), block_validate_exception,
                 "Incorrect block producer key: expected ${e} but got ${a}",
                 ("e", producer.signing_key)("a", public_key_type(next_block.signee())));
N
Nathan Hourt 已提交
1423

1424
   if(!(skip&skip_producer_schedule_check)) {
1425 1426 1427
      EOS_ASSERT(next_block.producer == producer.owner, block_validate_exception,
                 "Producer produced block at wrong time",
                 ("block producer",next_block.producer)("scheduled producer",producer.owner));
N
Nathan Hourt 已提交
1428 1429
   }

1430 1431 1432
   auto expected_schedule_version = get_global_properties().active_producers.version;
   EOS_ASSERT( next_block.schedule_version == expected_schedule_version , block_validate_exception,"wrong producer schedule version specified ${x} expectd ${y}",
               ("x", next_block.schedule_version)("y",expected_schedule_version) );
A
arhag 已提交
1433

N
Nathan Hourt 已提交
1434
   return producer;
1435
} FC_CAPTURE_AND_RETHROW( (block_header(next_block))) }
N
Nathan Hourt 已提交
1436

1437
void chain_controller::create_block_summary(const signed_block& next_block) {
1438
   auto sid = next_block.block_num() & 0xffff;
1439
   _db.modify( _db.get<block_summary_object,by_id>(sid), [&](block_summary_object& p) {
1440 1441
         p.block_id = next_block.id();
   });
N
Nathan Hourt 已提交
1442 1443
}

1444 1445
/**
 *  Takes the top config::producer_count producers by total vote excluding any producer whose
1446
 *  block_signing_key is null.
1447 1448
 */
producer_schedule_type chain_controller::_calculate_producer_schedule()const {
1449
   producer_schedule_type schedule = get_global_properties().new_active_producers;
1450

1451 1452 1453 1454
   const auto& hps = _head_producer_schedule();
   schedule.version = hps.version;
   if( hps != schedule )
      ++schedule.version;
1455 1456 1457 1458 1459 1460
   return schedule;
}

/**
 *  Returns the most recent and/or pending producer schedule
 */
D
Daniel Larimer 已提交
1461
const shared_producer_schedule_type& chain_controller::_head_producer_schedule()const {
1462
   const auto& gpo = get_global_properties();
1463
   if( gpo.pending_active_producers.size() )
1464 1465 1466 1467
      return gpo.pending_active_producers.back().second;
   return gpo.active_producers;
}

1468
void chain_controller::update_global_properties(const signed_block& b) { try {
1469 1470
   // If we're at the end of a round, update the BlockchainConfiguration, producer schedule
   // and "producers" special account authority
1471 1472 1473 1474 1475
   if( is_start_of_round( b.block_num() ) ) {
      auto schedule = _calculate_producer_schedule();
      if( b.new_producers )
      {
          FC_ASSERT( schedule == *b.new_producers, "pending producer set different than expected" );
1476 1477
      }
      const auto& gpo = get_global_properties();
1478 1479

      if( _head_producer_schedule() != schedule ) {
1480
         //wlog( "change in producer schedule pending irreversible: ${s}",  ("s", b.new_producers ) );
1481
         FC_ASSERT( b.new_producers, "pending producer set changed but block didn't indicate it" );
1482
      }
1483 1484 1485 1486
      _db.modify( gpo, [&]( auto& props ) {
         if( props.pending_active_producers.size() && props.pending_active_producers.back().first == b.block_num() )
            props.pending_active_producers.back().second = schedule;
         else
D
Daniel Larimer 已提交
1487
         {
1488 1489
            props.pending_active_producers.emplace_back( props.pending_active_producers.get_allocator() );
            // props.pending_active_producers.size()+1, props.pending_active_producers.get_allocator() );
D
Daniel Larimer 已提交
1490 1491 1492
            auto& back = props.pending_active_producers.back();
            back.first = b.block_num();
            back.second = schedule;
1493

D
Daniel Larimer 已提交
1494
         }
1495 1496
      });

1497
      _update_producers_authority();
1498
   }
1499
} FC_CAPTURE_AND_RETHROW() }
1500

1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
void chain_controller::_update_producers_authority() {
   const auto& gpo = get_global_properties();
   uint32_t authority_threshold = EOS_PERCENT_CEIL(gpo.active_producers.producers.size(), config::producers_authority_threshold_pct);
   auto active_producers_authority = authority(authority_threshold, {}, {});
   for(auto& name : gpo.active_producers.producers ) {
      active_producers_authority.accounts.push_back({{name.producer_name, config::active_name}, 1});
   }

   auto& po = _db.get<permission_object, by_owner>( boost::make_tuple(config::producers_account_name,
                                                                      config::active_name ) );
   _db.modify(po,[active_producers_authority] (permission_object& po) {
      po.auth = active_producers_authority;
   });
}

1516
void chain_controller::add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts ) {
1517
   for (const auto& i : checkpts)
N
Nathan Hourt 已提交
1518 1519 1520
      _checkpoints[i.first] = i.second;
}

1521
bool chain_controller::before_last_checkpoint()const {
N
Nathan Hourt 已提交
1522 1523 1524
   return (_checkpoints.size() > 0) && (_checkpoints.rbegin()->first >= head_block_num());
}

1525
const global_property_object& chain_controller::get_global_properties()const {
1526
   return _db.get<global_property_object>();
N
Nathan Hourt 已提交
1527 1528
}

1529
const dynamic_global_property_object&chain_controller::get_dynamic_global_properties() const {
1530
   return _db.get<dynamic_global_property_object>();
N
Nathan Hourt 已提交
1531 1532
}

D
Daniel Larimer 已提交
1533
time_point chain_controller::head_block_time()const {
N
Nathan Hourt 已提交
1534 1535 1536
   return get_dynamic_global_properties().time;
}

1537
uint32_t chain_controller::head_block_num()const {
N
Nathan Hourt 已提交
1538 1539 1540
   return get_dynamic_global_properties().head_block_number;
}

1541
block_id_type chain_controller::head_block_id()const {
N
Nathan Hourt 已提交
1542 1543 1544
   return get_dynamic_global_properties().head_block_id;
}

D
Daniel Larimer 已提交
1545
account_name chain_controller::head_block_producer() const {
1546 1547 1548
   auto b = _fork_db.fetch_block(head_block_id());
   if( b ) return b->data.producer;

N
Nathan Hourt 已提交
1549
   if (auto head_block = fetch_block_by_id(head_block_id()))
1550
      return head_block->producer;
N
Nathan Hourt 已提交
1551 1552 1553
   return {};
}

1554
const producer_object& chain_controller::get_producer(const account_name& owner_name) const
D
Daniel Larimer 已提交
1555
{ try {
B
Bart Wyatt 已提交
1556
   return _db.get<producer_object, by_owner>(owner_name);
D
Daniel Larimer 已提交
1557
} FC_CAPTURE_AND_RETHROW( (owner_name) ) }
N
Nathan Hourt 已提交
1558

1559
const permission_object&   chain_controller::get_permission( const permission_level& level )const
1560
{ try {
1561
   FC_ASSERT( !level.actor.empty() && !level.permission.empty(), "Invalid permission" );
1562
   return _db.get<permission_object, by_owner>( boost::make_tuple(level.actor,level.permission) );
1563
} EOS_RETHROW_EXCEPTIONS( chain::permission_query_exception, "Failed to retrieve permission: ${level}", ("level", level) ) }
1564

1565
uint32_t chain_controller::last_irreversible_block_num() const {
N
Nathan Hourt 已提交
1566
   return get_dynamic_global_properties().last_irreversible_block_num;
N
Nathan Hourt 已提交
1567 1568
}

D
Daniel Larimer 已提交
1569
void chain_controller::_initialize_indexes() {
1570 1571
   _db.add_index<account_index>();
   _db.add_index<permission_index>();
1572
   _db.add_index<permission_usage_index>();
1573
   _db.add_index<permission_link_index>();
1574
   _db.add_index<action_permission_index>();
D
Daniel Larimer 已提交
1575 1576 1577



1578 1579
   _db.add_index<contracts::table_id_multi_index>();
   _db.add_index<contracts::key_value_index>();
D
Daniel Larimer 已提交
1580
   _db.add_index<contracts::index64_index>();
1581
   _db.add_index<contracts::index128_index>();
1582
   _db.add_index<contracts::index256_index>();
A
arhag 已提交
1583
   _db.add_index<contracts::index_double_index>();
A
arhag 已提交
1584

1585 1586 1587 1588
   _db.add_index<global_property_multi_index>();
   _db.add_index<dynamic_global_property_multi_index>();
   _db.add_index<block_summary_multi_index>();
   _db.add_index<transaction_multi_index>();
1589
   _db.add_index<generated_transaction_multi_index>();
1590
   _db.add_index<producer_multi_index>();
1591
   _db.add_index<scope_sequence_multi_index>();
N
Nathan Hourt 已提交
1592 1593
}

D
Daniel Larimer 已提交
1594
void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
N
Nathan Hourt 已提交
1595
{ try {
1596
   if (!_db.find<global_property_object>()) {
N
Nathan Hourt 已提交
1597 1598
      _db.with_write_lock([this, &starter] {
         auto initial_timestamp = starter.get_chain_start_time();
D
Daniel Larimer 已提交
1599 1600 1601
         FC_ASSERT(initial_timestamp != time_point(), "Must initialize genesis timestamp." );
         FC_ASSERT( block_timestamp_type(initial_timestamp) == initial_timestamp,
                    "Genesis timestamp must be divisible by config::block_interval_ms" );
N
Nathan Hourt 已提交
1602

1603
         // Create global properties
1604
         const auto& gp = _db.create<global_property_object>([&starter](global_property_object& p) {
N
Nathan Hourt 已提交
1605 1606
            p.configuration = starter.get_chain_start_configuration();
            p.active_producers = starter.get_chain_start_producers();
1607
            p.new_active_producers = starter.get_chain_start_producers();
1608
         });
1609

1610
         _db.create<dynamic_global_property_object>([&](dynamic_global_property_object& p) {
N
Nathan Hourt 已提交
1611
            p.time = initial_timestamp;
A
arhag 已提交
1612
            //p.recent_slots_filled = uint64_t(-1);
1613
         });
N
Nathan Hourt 已提交
1614

1615 1616
         _resource_limits.initialize_chain();

N
Nathan Hourt 已提交
1617
         // Initialize block summary index
1618 1619
         for (int i = 0; i < 0x10000; i++)
            _db.create<block_summary_object>([&](block_summary_object&) {});
N
Nathan Hourt 已提交
1620

B
Bart Wyatt 已提交
1621
         starter.prepare_database(*this, _db);
1622
         _update_producers_authority();
1623 1624
      });
   }
N
Nathan Hourt 已提交
1625 1626
} FC_CAPTURE_AND_RETHROW() }

N
Nathan Hourt 已提交
1627

1628
void chain_controller::replay() {
1629
   ilog("Replaying blockchain");
N
Nathan Hourt 已提交
1630
   auto start = fc::time_point::now();
K
Kevin Heifner 已提交
1631

K
Kevin Heifner 已提交
1632
   auto on_exit = fc::make_scoped_exit([&_currently_replaying_blocks = _currently_replaying_blocks](){
K
Kevin Heifner 已提交
1633 1634 1635 1636
      _currently_replaying_blocks = false;
   });
   _currently_replaying_blocks = true;

1637 1638 1639
   auto last_block = _block_log.read_head();
   if (!last_block) {
      elog("No blocks in block log; skipping replay");
N
Nathan Hourt 已提交
1640 1641 1642 1643 1644
      return;
   }

   const auto last_block_num = last_block->block_num();

1645
   ilog("Replaying ${n} blocks...", ("n", last_block_num) );
1646 1647 1648 1649 1650
   for (uint32_t i = 1; i <= last_block_num; ++i) {
      if (i % 5000 == 0)
         std::cerr << "   " << double(i*100)/last_block_num << "%   "<<i << " of " <<last_block_num<<"   \n";
      fc::optional<signed_block> block = _block_log.read_block_by_num(i);
      FC_ASSERT(block, "Could not find block #${n} in block_log!", ("n", i));
D
Daniel Larimer 已提交
1651
      _apply_block(*block, skip_producer_signature |
N
Nathan Hourt 已提交
1652 1653 1654 1655
                          skip_transaction_signatures |
                          skip_transaction_dupe_check |
                          skip_tapos_check |
                          skip_producer_schedule_check |
1656 1657
                          skip_authority_check |
                          received_block);
N
Nathan Hourt 已提交
1658 1659
   }
   auto end = fc::time_point::now();
1660 1661
   ilog("Done replaying ${n} blocks, elapsed time: ${t} sec",
        ("n", head_block_num())("t",double((end-start).count())/1000000.0));
N
Nathan Hourt 已提交
1662

1663
   _db.set_revision(head_block_num());
1664
}
N
Nathan Hourt 已提交
1665

D
Daniel Larimer 已提交
1666
void chain_controller::_spinup_db() {
1667 1668 1669 1670 1671
   // Rewind the database to the last irreversible block
   _db.with_write_lock([&] {
      _db.undo_all();
      FC_ASSERT(_db.revision() == head_block_num(), "Chainbase revision does not match head block num",
                ("rev", _db.revision())("head_block", head_block_num()));
1672

1673 1674
   });
}
N
Nathan Hourt 已提交
1675

D
Daniel Larimer 已提交
1676
void chain_controller::_spinup_fork_db()
N
Nathan Hourt 已提交
1677
{
1678 1679 1680 1681 1682 1683 1684 1685
   fc::optional<signed_block> last_block = _block_log.read_head();
   if(last_block.valid()) {
      _fork_db.start_block(*last_block);
      if (last_block->id() != head_block_id()) {
           FC_ASSERT(head_block_num() == 0, "last block ID does not match current chain state",
                     ("last_block->id", last_block->id())("head_block_num",head_block_num()));
      }
   }
N
Nathan Hourt 已提交
1686 1687
}

D
Daniel Larimer 已提交
1688
/*
1689 1690
ProducerRound chain_controller::calculate_next_round(const signed_block& next_block) {
   auto schedule = _admin->get_next_round(_db);
N
Nathan Hourt 已提交
1691 1692 1693 1694
   auto changes = get_global_properties().active_producers - schedule;
   EOS_ASSERT(boost::range::equal(next_block.producer_changes, changes), block_validate_exception,
              "Unexpected round changes in new block header",
              ("expected changes", changes)("block changes", next_block.producer_changes));
1695

P
Pravin 已提交
1696 1697
   fc::time_point tp = (fc::time_point)next_block.timestamp;
   utilities::rand::random rng(tp.sec_since_epoch());
1698 1699
   rng.shuffle(schedule);
   return schedule;
D
Daniel Larimer 已提交
1700
}*/
1701

1702
void chain_controller::update_global_dynamic_data(const signed_block& b) {
1703
   const dynamic_global_property_object& _dgp = _db.get<dynamic_global_property_object>();
N
Nathan Hourt 已提交
1704

1705 1706 1707
   const auto& bmroot = _dgp.block_merkle_root.get_root();
   FC_ASSERT( bmroot == b.block_mroot, "block merkle root does not match expected value" );

P
Pravin 已提交
1708
   uint32_t missed_blocks = head_block_num() == 0? 1 : get_slot_at_time((fc::time_point)b.timestamp);
1709
   assert(missed_blocks != 0);
N
Nathan Hourt 已提交
1710
   missed_blocks--;
N
Nathan Hourt 已提交
1711

1712 1713
//   if (missed_blocks)
//      wlog("Blockchain continuing after gap of ${b} missed blocks", ("b", missed_blocks));
N
Nathan Hourt 已提交
1714

1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728
   if (!(_skip_flags & skip_missed_block_penalty)) {
      for (uint32_t i = 0; i < missed_blocks; ++i) {
         const auto &producer_missed = get_producer(get_scheduled_producer(i + 1));
         if (producer_missed.owner != b.producer) {
            /*
            const auto& producer_account = producer_missed.producer_account(*this);
            if( (fc::time_point::now() - b.timestamp) < fc::seconds(30) )
               wlog( "Producer ${name} missed block ${n} around ${t}", ("name",producer_account.name)("n",b.block_num())("t",b.timestamp) );
               */

            _db.modify(producer_missed, [&](producer_object &w) {
               w.total_missed++;
            });
         }
N
Nathan Hourt 已提交
1729 1730 1731
      }
   }

1732 1733
   const auto& props = get_global_properties();

N
Nathan Hourt 已提交
1734
   // dynamic global properties updating
1735
   _db.modify( _dgp, [&]( dynamic_global_property_object& dgp ){
N
Nathan Hourt 已提交
1736 1737 1738
      dgp.head_block_number = b.block_num();
      dgp.head_block_id = b.id();
      dgp.time = b.timestamp;
1739
      dgp.current_producer = b.producer;
N
Nathan Hourt 已提交
1740 1741
      dgp.current_absolute_slot += missed_blocks+1;

A
arhag 已提交
1742
      /*
N
Nathan Hourt 已提交
1743 1744 1745 1746 1747
      // If we've missed more blocks than the bitmap stores, skip calculations and simply reset the bitmap
      if (missed_blocks < sizeof(dgp.recent_slots_filled) * 8) {
         dgp.recent_slots_filled <<= 1;
         dgp.recent_slots_filled += 1;
         dgp.recent_slots_filled <<= missed_blocks;
1748
      } else
1749
         if(config::percent_100 * get_global_properties().active_producers.producers.size() / blocks_per_round() > config::required_producer_participation)
1750 1751 1752
            dgp.recent_slots_filled = uint64_t(-1);
         else
            dgp.recent_slots_filled = 0;
A
arhag 已提交
1753
      */
1754
      dgp.block_merkle_root.append( head_block_id() );
N
Nathan Hourt 已提交
1755 1756 1757 1758 1759
   });

   _fork_db.set_max_size( _dgp.head_block_number - _dgp.last_irreversible_block_num + 1 );
}

1760
void chain_controller::update_signing_producer(const producer_object& signing_producer, const signed_block& new_block)
N
Nathan Hourt 已提交
1761 1762
{
   const dynamic_global_property_object& dpo = get_dynamic_global_properties();
P
Pravin 已提交
1763
   uint64_t new_block_aslot = dpo.current_absolute_slot + get_slot_at_time( (fc::time_point)new_block.timestamp );
N
Nathan Hourt 已提交
1764

1765
   _db.modify( signing_producer, [&]( producer_object& _wit )
N
Nathan Hourt 已提交
1766 1767 1768 1769 1770 1771
   {
      _wit.last_aslot = new_block_aslot;
      _wit.last_confirmed_block_num = new_block.block_num();
   } );
}

1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
void chain_controller::update_permission_usage( const transaction_metadata& meta ) {
   // for any transaction not sent by code, update the affirmative last time a given permission was used
   if (!meta.sender) {
      for( const auto& act : meta.trx().actions ) {
         for( const auto& auth : act.authorization ) {
            const auto *puo = _db.find<permission_usage_object, by_account_permission>(boost::make_tuple(auth.actor, auth.permission));
            if (puo) {
               _db.modify(*puo, [this](permission_usage_object &pu) {
                  pu.last_used = head_block_time();
               });
            } else {
               _db.create<permission_usage_object>([this, &auth](permission_usage_object &pu){
                  pu.account = auth.actor;
                  pu.permission = auth.permission;
                  pu.last_used = head_block_time();
               });
            }
         }
      }
   }
}

1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804
void chain_controller::update_or_create_producers( const producer_schedule_type& producers ) {
   for ( auto prod : producers.producers ) {
      if ( _db.find<producer_object, by_owner>(prod.producer_name) == nullptr ) {
         _db.create<producer_object>( [&]( auto& pro ) {
            pro.owner       = prod.producer_name;
            pro.signing_key = prod.block_signing_key;
         });
      }
   }
}

1805
void chain_controller::update_last_irreversible_block()
N
Nathan Hourt 已提交
1806 1807 1808 1809
{
   const global_property_object& gpo = get_global_properties();
   const dynamic_global_property_object& dpo = get_dynamic_global_properties();

N
Nathan Hourt 已提交
1810
   vector<const producer_object*> producer_objs;
1811
   producer_objs.reserve(gpo.active_producers.producers.size());
D
Daniel Larimer 已提交
1812

1813
   std::transform(gpo.active_producers.producers.begin(),
1814
                  gpo.active_producers.producers.end(), std::back_inserter(producer_objs),
D
Daniel Larimer 已提交
1815
                  [this](const producer_key& pk) { return &get_producer(pk.producer_name); });
N
Nathan Hourt 已提交
1816

D
Daniel Larimer 已提交
1817
   static_assert(config::irreversible_threshold_percent > 0, "irreversible threshold must be nonzero");
N
Nathan Hourt 已提交
1818

D
Daniel Larimer 已提交
1819
   size_t offset = EOS_PERCENT(producer_objs.size(), config::percent_100- config::irreversible_threshold_percent);
1820 1821
   std::nth_element(producer_objs.begin(), producer_objs.begin() + offset, producer_objs.end(),
      [](const producer_object* a, const producer_object* b) {
N
Nathan Hourt 已提交
1822
         return a->last_confirmed_block_num < b->last_confirmed_block_num;
1823
      });
N
Nathan Hourt 已提交
1824

1825 1826 1827 1828 1829 1830
   uint32_t new_last_irreversible_block_num = producer_objs[offset]->last_confirmed_block_num;
   // TODO: right now the code cannot handle the head block being irreversible for reasons that are purely
   // implementation details.  We can and should remove this special case once the rest of the logic is fixed.
   if (producer_objs.size() == 1) {
      new_last_irreversible_block_num -= 1;
   }
1831

N
Nathan Hourt 已提交
1832

1833
   if (new_last_irreversible_block_num > dpo.last_irreversible_block_num) {
1834
      _db.modify(dpo, [&](dynamic_global_property_object& _dpo) {
N
Nathan Hourt 已提交
1835
         _dpo.last_irreversible_block_num = new_last_irreversible_block_num;
1836
      });
N
Nathan Hourt 已提交
1837
   }
1838 1839

   // Write newly irreversible blocks to disk. First, get the number of the last block on disk...
1840
   auto old_last_irreversible_block = _block_log.head();
1841
   unsigned last_block_on_disk = 0;
1842 1843 1844
   // If this is null, there are no blocks on disk, so the zero is correct
   if (old_last_irreversible_block)
      last_block_on_disk = old_last_irreversible_block->block_num();
1845

1846
   if (last_block_on_disk < new_last_irreversible_block_num) {
1847 1848 1849 1850
      for (auto block_to_write = last_block_on_disk + 1;
           block_to_write <= new_last_irreversible_block_num;
           ++block_to_write) {
         auto block = fetch_block_by_number(block_to_write);
1851
         FC_ASSERT( block, "unable to find last irreversible block to write" );
1852
         _block_log.append(*block);
K
Kevin Heifner 已提交
1853
         applied_irreversible_block(*block);
1854
      }
1855 1856
   }

1857 1858 1859 1860 1861
   /// TODO: use upper / lower bound to find
   optional<producer_schedule_type> new_producer_schedule;
   for( const auto& item : gpo.pending_active_producers ) {
      if( item.first < new_last_irreversible_block_num ) {
         new_producer_schedule = item.second;
1862
      }
1863 1864 1865 1866 1867 1868 1869 1870 1871
   }
   if( new_producer_schedule ) {
      update_or_create_producers( *new_producer_schedule );
      _db.modify( gpo, [&]( auto& props ){
           boost::range::remove_erase_if(props.pending_active_producers,
                                         [new_last_irreversible_block_num](const typename decltype(props.pending_active_producers)::value_type& v) -> bool {
                                            return v.first <= new_last_irreversible_block_num;
                                         });
           if( props.active_producers.version != new_producer_schedule->version ) {
1872
              props.active_producers = *new_producer_schedule;
1873 1874
           }
      });
1875 1876
   }

N
Nathan Hourt 已提交
1877 1878
   // Trim fork_database and undo histories
   _fork_db.set_max_size(head_block_num() - new_last_irreversible_block_num + 1);
1879
   _db.commit(new_last_irreversible_block_num);
N
Nathan Hourt 已提交
1880 1881
}

1882
void chain_controller::clear_expired_transactions()
N
Nathan Hourt 已提交
1883 1884
{ try {
   //Look for expired transactions in the deduplication list, and remove them.
D
Daniel Larimer 已提交
1885
   //transactions must have expired by at least two forking windows in order to be removed.
1886
   auto& transaction_idx = _db.get_mutable_index<transaction_multi_index>();
N
Nathan Hourt 已提交
1887
   const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
1888
   while( (!dedupe_index.empty()) && (head_block_time() > fc::time_point(dedupe_index.rbegin()->expiration) ) )
N
Nathan Hourt 已提交
1889
      transaction_idx.remove(*dedupe_index.rbegin());
1890

1891
   //Look for expired transactions in the pending generated list, and remove them.
D
Daniel Larimer 已提交
1892
   //transactions must have expired by at least two forking windows in order to be removed.
1893
   auto& generated_transaction_idx = _db.get_mutable_index<generated_transaction_multi_index>();
B
Bart Wyatt 已提交
1894
   const auto& generated_index = generated_transaction_idx.indices().get<by_expiration>();
B
Bart Wyatt 已提交
1895 1896 1897
   while( (!generated_index.empty()) && (head_block_time() > generated_index.rbegin()->expiration) ) {
      _destroy_generated_transaction(*generated_index.rbegin());
   }
B
Bart Wyatt 已提交
1898

N
Nathan Hourt 已提交
1899 1900 1901 1902
} FC_CAPTURE_AND_RETHROW() }

using boost::container::flat_set;

D
Daniel Larimer 已提交
1903
account_name chain_controller::get_scheduled_producer(uint32_t slot_num)const
N
Nathan Hourt 已提交
1904 1905
{
   const dynamic_global_property_object& dpo = get_dynamic_global_properties();
N
Nathan Hourt 已提交
1906
   uint64_t current_aslot = dpo.current_absolute_slot + slot_num;
1907
   const auto& gpo = _db.get<global_property_object>();
1908
   auto number_of_active_producers = gpo.active_producers.producers.size();
1909 1910
   auto index = current_aslot % (number_of_active_producers * config::producer_repetitions);
   index /= config::producer_repetitions;
1911 1912
   FC_ASSERT( gpo.active_producers.producers.size() > 0, "no producers defined" );

1913
   return gpo.active_producers.producers[index].producer_name;
N
Nathan Hourt 已提交
1914 1915
}

D
Daniel Larimer 已提交
1916
block_timestamp_type chain_controller::get_slot_time(uint32_t slot_num)const
N
Nathan Hourt 已提交
1917
{
P
Pravin 已提交
1918
   if( slot_num == 0)
D
Daniel Larimer 已提交
1919
      return block_timestamp_type();
N
Nathan Hourt 已提交
1920 1921 1922 1923 1924 1925

   const dynamic_global_property_object& dpo = get_dynamic_global_properties();

   if( head_block_num() == 0 )
   {
      // n.b. first block is at genesis_time plus one block interval
P
Pravin 已提交
1926 1927 1928
      auto genesis_time = block_timestamp_type(dpo.time);
      genesis_time.slot += slot_num;
      return (fc::time_point)genesis_time;
N
Nathan Hourt 已提交
1929 1930
   }

D
Daniel Larimer 已提交
1931
   auto head_block_abs_slot = block_timestamp_type(head_block_time());
P
Pravin 已提交
1932
   head_block_abs_slot.slot += slot_num;
D
Daniel Larimer 已提交
1933
   return head_block_abs_slot;
N
Nathan Hourt 已提交
1934 1935
}

D
Daniel Larimer 已提交
1936
uint32_t chain_controller::get_slot_at_time( block_timestamp_type when )const
N
Nathan Hourt 已提交
1937
{
D
Daniel Larimer 已提交
1938
   auto first_slot_time = get_slot_time(1);
N
Nathan Hourt 已提交
1939 1940
   if( when < first_slot_time )
      return 0;
D
Daniel Larimer 已提交
1941
   return block_timestamp_type(when).slot - first_slot_time.slot + 1;
N
Nathan Hourt 已提交
1942 1943
}

1944
uint32_t chain_controller::producer_participation_rate()const
N
Nathan Hourt 已提交
1945
{
A
arhag 已提交
1946 1947 1948
   //const dynamic_global_property_object& dpo = get_dynamic_global_properties();
   //return uint64_t(config::percent_100) * __builtin_popcountll(dpo.recent_slots_filled) / 64;
   return static_cast<uint32_t>(config::percent_100); // Ignore participation rate for now until we construct a better metric.
N
Nathan Hourt 已提交
1949 1950
}

D
Daniel Larimer 已提交
1951 1952
void chain_controller::_set_apply_handler( account_name contract, scope_name scope, action_name action, apply_handler v ) {
   _apply_handlers[contract][make_pair(scope,action)] = v;
1953
}
N
Nathan Hourt 已提交
1954

1955
static void log_handled_exceptions(const transaction& trx) {
B
Bart Wyatt 已提交
1956 1957 1958 1959
   try {
      throw;
   } catch (const checktime_exceeded&) {
      throw;
1960
   } FC_CAPTURE_AND_LOG((trx));
B
Bart Wyatt 已提交
1961 1962
}

1963
transaction_trace chain_controller::__apply_transaction( transaction_metadata& meta )
1964
{ try {
1965
   transaction_trace result(meta.id);
D
Daniel Larimer 已提交
1966 1967 1968 1969 1970 1971

   for (const auto &act : meta.trx().context_free_actions) {
      apply_context context(*this, _db, act, meta);
      context.context_free = true;
      context.exec();
      fc::move_append(result.action_traces, std::move(context.results.applied_actions));
1972
      FC_ASSERT( result.deferred_transaction_requests.size() == 0 );
D
Daniel Larimer 已提交
1973 1974
   }

1975
   for (const auto &act : meta.trx().actions) {
1976
      apply_context context(*this, _db, act, meta);
1977
      context.exec();
1978
      context.results.applied_actions.back().auths_used = act.authorization.size() - context.unused_authorizations().size();
1979
      fc::move_append(result.action_traces, std::move(context.results.applied_actions));
1980
      fc::move_append(result.deferred_transaction_requests, std::move(context.results.deferred_transaction_requests));
1981
   }
B
Bart Wyatt 已提交
1982

1983
   update_resource_usage(result, meta);
B
Bart Wyatt 已提交
1984

1985
   update_permission_usage(meta);
1986
   record_transaction(meta.trx());
1987
   return result;
1988
} FC_CAPTURE_AND_RETHROW() }
B
Bart Wyatt 已提交
1989

1990
transaction_trace chain_controller::_apply_transaction( transaction_metadata& meta ) { try {
1991 1992 1993 1994 1995 1996 1997
   auto execute = [this](transaction_metadata& meta) -> transaction_trace {
      try {
         auto temp_session = _db.start_undo_session(true);
         auto result =  __apply_transaction(meta);
         temp_session.squash();
         return result;
      } catch (...) {
B
Bucky Kittinger 已提交
1998
         if (meta.is_implicit) {
1999 2000 2001
            try {
               throw;
            } FC_CAPTURE_AND_LOG((meta.id));
B
Bucky Kittinger 已提交
2002 2003 2004 2005 2006
            transaction_trace result(meta.id);
            result.status = transaction_trace::hard_fail;
            return result;
         }

2007 2008 2009 2010
         // if there is no sender, there is no error handling possible, rethrow
         if (!meta.sender) {
            throw;
         }
2011

2012 2013 2014 2015
         // log exceptions we can handle with the error handle, throws otherwise
         log_handled_exceptions(meta.trx());

         return _apply_error(meta);
B
Bart Wyatt 已提交
2016
      }
2017
   };
2018

2019 2020 2021 2022
   auto start = fc::time_point::now();
   auto result = execute(meta);
   result._profiling_us = fc::time_point::now() - start;
   return result;
2023
} FC_CAPTURE_AND_RETHROW( (transaction_header(meta.trx())) ) }
B
Bart Wyatt 已提交
2024 2025 2026 2027 2028 2029

transaction_trace chain_controller::_apply_error( transaction_metadata& meta ) {
   transaction_trace result(meta.id);
   result.status = transaction_trace::soft_fail;

   transaction etrx;
A
arhag 已提交
2030
   etrx.actions.emplace_back(vector<permission_level>{{*meta.sender,config::active_name}},
2031
                             contracts::onerror(meta.raw_data, meta.raw_data + meta.raw_size) );
B
Bart Wyatt 已提交
2032 2033

   try {
2034 2035
      auto temp_session = _db.start_undo_session(true);

2036
      apply_context context(*this, _db, etrx.actions.front(), meta);
D
Daniel Larimer 已提交
2037
      context.exec();
2038
      fc::move_append(result.action_traces, std::move(context.results.applied_actions));
2039
      fc::move_append(result.deferred_transaction_requests, std::move(context.results.deferred_transaction_requests));
B
Bart Wyatt 已提交
2040

B
Bart Wyatt 已提交
2041
      uint32_t act_usage = result.action_traces.size();
2042

2043
      update_resource_usage(result, meta);
2044
      record_transaction(meta.trx());
2045 2046

      temp_session.squash();
B
Bart Wyatt 已提交
2047
      return result;
2048

B
Bart Wyatt 已提交
2049
   } catch (...) {
2050 2051 2052 2053
      // log exceptions we can handle with the error handle, throws otherwise
      log_handled_exceptions(etrx);

      // fall through to marking this tx as hard-failing
B
Bart Wyatt 已提交
2054 2055 2056 2057
   }

   // if we have an objective error, on an error handler, we return hard fail for the trx
   result.status = transaction_trace::hard_fail;
2058 2059 2060
   return result;
}

B
Bart Wyatt 已提交
2061 2062
void chain_controller::_destroy_generated_transaction( const generated_transaction_object& gto ) {
   auto& generated_transaction_idx = _db.get_mutable_index<generated_transaction_multi_index>();
2063
   _resource_limits.add_pending_account_ram_usage(gto.payer, -( config::billable_size_v<generated_transaction_object> + gto.packed_trx.size()));
B
Bart Wyatt 已提交
2064 2065 2066 2067 2068 2069
   generated_transaction_idx.remove(gto);

}

void chain_controller::_create_generated_transaction( const deferred_transaction& dto ) {
   size_t trx_size = fc::raw::pack_size(dto);
2070
   _resource_limits.add_pending_account_ram_usage(
B
Bart Wyatt 已提交
2071
      dto.payer,
2072
      (config::billable_size_v<generated_transaction_object> + (int64_t)trx_size)
B
Bart Wyatt 已提交
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
   );

   _db.create<generated_transaction_object>([&](generated_transaction_object &obj) {
      obj.trx_id = dto.id();
      obj.sender = dto.sender;
      obj.sender_id = dto.sender_id;
      obj.payer = dto.payer;
      obj.expiration = dto.expiration;
      obj.delay_until = dto.execute_after;
      obj.published = head_block_time();
      obj.packed_trx.resize(trx_size);
      fc::datastream<char *> ds(obj.packed_trx.data(), obj.packed_trx.size());
      fc::raw::pack(ds, dto);
   });
}

2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102
vector<transaction_trace> chain_controller::push_deferred_transactions( bool flush, uint32_t skip )
{ try {
   if( !_pending_block ) {
      _start_pending_block( true );
   }

   return with_skip_flags(skip, [&]() {
      return _db.with_write_lock([&]() {
         return _push_deferred_transactions( flush );
      });
   });
} FC_CAPTURE_AND_RETHROW() }

vector<transaction_trace> chain_controller::_push_deferred_transactions( bool flush )
B
Bart Wyatt 已提交
2103
{
2104 2105
   FC_ASSERT( _pending_block, " block not started" );

2106 2107 2108 2109 2110 2111
   if (flush && _pending_cycle_trace && _pending_cycle_trace->shard_traces.size() > 0) {
      // TODO: when we go multithreaded this will need a better way to see if there are flushable
      // deferred transactions in the shards
      auto maybe_start_new_cycle = [&]() {
         for (const auto &st: _pending_cycle_trace->shard_traces) {
            for (const auto &tr: st.transaction_traces) {
2112 2113 2114 2115 2116 2117 2118 2119 2120
               for (const auto &req: tr.deferred_transaction_requests) {
                  if ( req.contains<deferred_transaction>() ) {
                     const auto& dt = req.get<deferred_transaction>();
                     if ( fc::time_point(dt.execute_after) <= head_block_time() ) {
                        // force a new cycle and break out
                        _finalize_pending_cycle();
                        _start_pending_cycle();
                        return;
                     }
2121 2122 2123 2124 2125
                  }
               }
            }
         }
      };
B
Bart Wyatt 已提交
2126

2127 2128
      maybe_start_new_cycle();
   }
B
Bart Wyatt 已提交
2129

B
Bart Wyatt 已提交
2130
   const auto& generated_transaction_idx = _db.get_index<generated_transaction_multi_index>();
2131 2132
   auto& generated_index = generated_transaction_idx.indices().get<by_delay>();
   vector<const generated_transaction_object*> candidates;
B
Bart Wyatt 已提交
2133

2134
   for( auto itr = generated_index.begin(); itr != generated_index.end() && (head_block_time() >= itr->delay_until); ++itr) {
2135 2136 2137
      const auto &gtrx = *itr;
      candidates.emplace_back(&gtrx);
   }
B
Bart Wyatt 已提交
2138

2139 2140 2141 2142 2143
   optional<fc::time_point> processing_deadline;
   if (_limits.max_deferred_transactions_us.count() > 0) {
      processing_deadline = fc::time_point::now() + _limits.max_deferred_transactions_us;
   }

2144
   vector<transaction_trace> res;
2145 2146 2147 2148
   for (const auto* trx_p: candidates) {
      if (!is_known_transaction(trx_p->trx_id)) {
         try {
            auto trx = fc::raw::unpack<deferred_transaction>(trx_p->packed_trx.data(), trx_p->packed_trx.size());
2149
            transaction_metadata mtrx (trx, trx_p->published, trx.sender, trx.sender_id, trx_p->packed_trx.data(), trx_p->packed_trx.size(), processing_deadline);
2150
            res.push_back( _push_transaction(std::move(mtrx)) );
2151 2152
         } FC_CAPTURE_AND_LOG((trx_p->trx_id)(trx_p->sender));
      }
B
Bart Wyatt 已提交
2153 2154

      _destroy_generated_transaction(*trx_p);
2155

2156
      if ( !processing_deadline || *processing_deadline <= fc::time_point::now() ) {
2157 2158
         break;
      }
B
Bart Wyatt 已提交
2159
   }
2160
   return res;
B
Bart Wyatt 已提交
2161 2162
}

D
Daniel Larimer 已提交
2163 2164 2165 2166 2167
const apply_handler* chain_controller::find_apply_handler( account_name receiver, account_name scope, action_name act ) const
{
   auto native_handler_scope = _apply_handlers.find( receiver );
   if( native_handler_scope != _apply_handlers.end() ) {
      auto handler = native_handler_scope->second.find( make_pair( scope, act ) );
2168
      if( handler != native_handler_scope->second.end() )
D
Daniel Larimer 已提交
2169 2170 2171 2172 2173
         return &handler->second;
   }
   return nullptr;
}

2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187
template<typename TransactionProcessing>
transaction_trace chain_controller::wrap_transaction_processing( transaction_metadata&& data, TransactionProcessing trx_processing )
{ try {
   FC_ASSERT( _pending_block, " block not started" );

   if (_limits.max_push_transaction_us.count() > 0) {
      auto newval = fc::time_point::now() + _limits.max_push_transaction_us;
      if ( !data.processing_deadline || newval < *data.processing_deadline ) {
         data.processing_deadline = newval;
      }
   }

   const transaction& trx = data.trx();

2188 2189
   FC_ASSERT( trx.region == 0, "currently only region 0 is supported" );

2190 2191
   //wdump((transaction_header(trx)));

2192 2193 2194 2195 2196
   auto temp_session = _db.start_undo_session(true);

   // for now apply the transaction serially but schedule it according to those invariants

   auto result = trx_processing(data);
2197
   _resource_limits.synchronize_account_ram_usage();
2198 2199 2200

   auto& bcycle = _pending_block->regions.back().cycles_summary.back();
   auto& bshard = bcycle.front();
B
Bart Wyatt 已提交
2201
   auto& bshard_trace = _pending_cycle_trace->shard_traces.at(0);
2202

B
Bart Wyatt 已提交
2203
   record_locks_for_data_access(result, bshard_trace.read_locks, bshard_trace.write_locks);
2204 2205 2206

   bshard.transactions.emplace_back( result );

2207 2208 2209 2210
   if( data.raw_trx.valid() && !data.is_implicit ) { // if an input transaction
      result.packed_trx_digest = data.packed_digest;
   }

2211 2212 2213 2214
   result.region_id   = 0; // Currently we only support region 0.
   result.cycle_index = _pending_block->regions.back().cycles_summary.size() - 1;
   result.shard_index = 0; // Currently we only have one shard per cycle.

B
Bart Wyatt 已提交
2215
   bshard_trace.append(result);
2216 2217 2218 2219

   // The transaction applied successfully. Merge its changes into the pending block session.
   temp_session.squash();

2220 2221
   //wdump((transaction_header(data.trx())));
   _pending_transaction_metas.emplace_back( move(data) );
2222 2223

   return result;
2224
} FC_CAPTURE_AND_RETHROW( (transaction_header(data.trx())) ) }
2225

D
Daniel Larimer 已提交
2226
} } /// eosio::chain