提交 9a5dbab4 编写于 作者: D Daniel Larimer

progress

上级 bc836de8
......@@ -9,6 +9,7 @@ add_library( eosio_chain2
block_header_state.cpp
block_state.cpp
fork_database.cpp
controller.cpp
# chain_config.cpp
# block_trace.cpp
# wast_to_wasm.cpp
......
......@@ -4,36 +4,28 @@
namespace eosio { namespace chain {
uint32_t block_header_state::calc_dpos_last_irreversible()const {
vector<uint32_t> irb;
irb.reserve( producer_to_last_produced.size() );
for( const auto& item : producer_to_last_produced )
irb.push_back(item.second);
vector<uint32_t> irb;
irb.reserve( producer_to_last_produced.size() );
for( const auto& item : producer_to_last_produced )
irb.push_back(item.second);
size_t offset = EOS_PERCENT(irb.size(), config::percent_100- config::irreversible_threshold_percent);
std::nth_element( irb.begin(), irb.begin() + offset, irb.end() );
size_t offset = EOS_PERCENT(irb.size(), config::percent_100- config::irreversible_threshold_percent);
std::nth_element( irb.begin(), irb.begin() + offset, irb.end() );
return irb[offset];
return irb[offset];
}
bool block_header_state::is_active_producer( account_name n )const {
return producer_to_last_produced.find(n) != producer_to_last_produced.end();
return producer_to_last_produced.find(n) != producer_to_last_produced.end();
}
producer_key block_header_state::scheduled_producer( block_timestamp_type t )const {
auto index = t.slot % (active_schedule.producers.size() * config::producer_repetitions);
index /= config::producer_repetitions;
return active_schedule.producers[index];
auto index = t.slot % (active_schedule.producers.size() * config::producer_repetitions);
index /= config::producer_repetitions;
return active_schedule.producers[index];
}
bool block_header_state::is_start_of_round( uint32_t block_num )const {
return 0 == (block_num % blocks_per_round());
}
uint32_t block_header_state::blocks_per_round()const {
return active_schedule.producers.size()*config::producer_repetitions;
}
/**
* Transitions the current header state into the next header state given the supplied signed block header.
......@@ -60,30 +52,28 @@ namespace eosio { namespace chain {
FC_ASSERT( h.block_mroot == result.blockroot_merkle.get_root(), "unexpected block merkle root" );
if( result.dpos_last_irreversible_blocknum >= pending_schedule_lib_num ) {
result.active_schedule = move(result.pending_schedule);
flat_map<account_name,uint32_t> new_producer_to_last_produced;
for( const auto& pro : result.active_schedule.producers ) {
auto existing = producer_to_last_produced.find( pro.producer_name );
if( existing != producer_to_last_produced.end() ) {
new_producer_to_last_produced[pro.producer_name] = existing->second;
} else {
new_producer_to_last_produced[pro.producer_name] = result.dpos_last_irreversible_blocknum;
}
}
result.producer_to_last_produced = move( new_producer_to_last_produced );
result.active_schedule = move(result.pending_schedule);
flat_map<account_name,uint32_t> new_producer_to_last_produced;
for( const auto& pro : result.active_schedule.producers ) {
auto existing = producer_to_last_produced.find( pro.producer_name );
if( existing != producer_to_last_produced.end() ) {
new_producer_to_last_produced[pro.producer_name] = existing->second;
} else {
new_producer_to_last_produced[pro.producer_name] = result.dpos_last_irreversible_blocknum;
}
}
result.producer_to_last_produced = move( new_producer_to_last_produced );
}
if( h.new_producers ) {
EOS_ASSERT( is_start_of_round( result.block_num ), block_validate_exception,
"Producer changes may only occur at the end of a round.");
FC_ASSERT( h.new_producers->version == result.active_schedule.version + 1, "wrong producer schedule version specified" );
FC_ASSERT( result.pending_schedule.producers.size() == 0,
"cannot set new pending producers until last pending is confirmed" );
result.pending_schedule = *h.new_producers;
result.pending_schedule_hash = digest_type::hash( result.pending_schedule );
result.pending_schedule_lib_num = h.block_num();
FC_ASSERT( h.new_producers->version == result.active_schedule.version + 1, "wrong producer schedule version specified" );
FC_ASSERT( result.pending_schedule.producers.size() == 0,
"cannot set new pending producers until last pending is confirmed" );
result.pending_schedule = *h.new_producers;
result.pending_schedule_hash = digest_type::hash( result.pending_schedule );
result.pending_schedule_lib_num = h.block_num();
}
result.header = h;
......
......@@ -91,28 +91,42 @@ namespace eosio { namespace chain {
for( uint32_t i = 1; i < block->regions.size(); ++i )
FC_ASSERT( block->regions[i-1].region < block->regions[i].region );
reset_trace();
bool found_trx = false;
trace = std::make_shared<block_trace>( block );
/// reserve region_trace
for( uint32_t r = 0; r < block->regions.size(); ++r ) {
// FC_ASSERT( block->regions[r].cycles_summary.size() >= 1, "must be at least one cycle" );
/// reserve cycle traces
for( uint32_t c = 0; c < block->regions[r].cycles_summary.size(); c++ ) {
// FC_ASSERT( block->regions[r].cycles_summary.size() >= 1, "must be at least one shard" );
/// reserve shard traces
for( uint32_t s = 0; s < block->regions[r].cycles_summary[c][s].transactions.size(); s++ ) {
} // end if block
}
void block_state::reset_trace() {
validated = false;
bool found_trx = false;
trace = std::make_shared<block_trace>( block );
auto num_regions = block->regions.size();
trace->region_traces.resize( num_regions );
/// reserve region_trace
for( uint32_t r = 0; r < num_regions; ++r ) {
auto num_cycles = block->regions[r].cycles_summary.size();
trace->region_traces[r].cycle_traces.resize( num_cycles );
// FC_ASSERT( block->regions[r].cycles_summary.size() >= 1, "must be at least one cycle" );
/// reserve cycle traces
for( uint32_t c = 0; c < num_cycles; c++ ) {
auto num_shards = block->regions[r].cycles_summary[c].size();
trace->region_traces[r].cycle_traces[c].shard_traces.resize( num_shards );
// FC_ASSERT( block->regions[r].cycles_summary.size() >= 1, "must be at least one shard" );
/// reserve shard traces
for( uint32_t s = 0; s < num_shards; ++s ) {
validate_shard_locks( block->regions[r].cycles_summary[c][s], s );
auto num_trx = block->regions[r].cycles_summary[c][s].transactions.size();
trace->region_traces[r].cycle_traces[c].shard_traces[s].transaction_traces.resize(num_trx);
for( uint32_t t = 0; t < num_trx; ++t ) {
found_trx = true;
// FC_ASSERT( block->regions[r].cycles.size() >= 1, "must be at least one trx" ); ///
//validate_shard_locks( block->.... )
/// reserve transaction trace...
}
}
}
FC_ASSERT( found_trx, "a block must contain at least one transaction (the implicit on block trx)" );
} // end if block
}
}
FC_ASSERT( found_trx, "a block must contain at least one transaction (the implicit on block trx)" );
}
......
#include <eosio/chain/controller.hpp>
#include <chainbase/database.hpp>
#include <chainbase/chainbase.hpp>
#include <eosio/chain/block_log.hpp>
#include <eosio/chain/fork_database.hpp>
#include <eosio/chain/block_summary_object.hpp>
#include <eosio/chain/global_property_object.hpp>
......@@ -18,7 +21,7 @@ using resource_limits::resource_limits_manager;
struct pending_state {
pending_state( database::session&& s )
:_db_session(s){}
:_db_session( move(s) ){}
block_timestamp_type _pending_time;
database::session _db_session;
......@@ -36,6 +39,19 @@ struct controller_impl {
controller::config conf;
controller& self;
block_id_type head_block_id()const {
return head->id;
}
time_point head_block_time()const {
return head->header.timestamp;
}
const block_header& head_block_header()const {
return head->header;
}
void pop_block() {
}
controller_impl( const controller::config& cfg, controller& s )
:db( cfg.shared_memory_dir,
......@@ -66,6 +82,7 @@ struct controller_impl {
}
void initialize_indicies() {
/*
db.add_index<account_index>();
db.add_index<permission_index>();
db.add_index<permission_usage_index>();
......@@ -86,6 +103,7 @@ struct controller_impl {
db.add_index<generated_transaction_multi_index>();
db.add_index<producer_multi_index>();
db.add_index<scope_sequence_multi_index>();
*/
resource_limits.initialize_database();
}
......@@ -114,6 +132,39 @@ struct controller_impl {
}
/**
* This method will backup all tranasctions in the current pending block,
* undo the pending block, call f(), and then push the pending transactions
* on top of the new state.
*/
template<typename Function>
auto without_pending_transactions( Function&& f )
{
#if 0
vector<transaction_metadata> old_input;
if( _pending_block )
old_input = move(_pending_transaction_metas);
clear_pending();
/** after applying f() push previously input transactions on top */
auto on_exit = fc::make_scoped_exit( [&](){
for( auto& t : old_input ) {
try {
if (!is_known_transaction(t.id))
_push_transaction( std::move(t) );
} catch ( ... ){}
}
});
#endif
pending.reset();
return f();
}
block_state_ptr push_block( const signed_block_ptr& b ) {
return without_pending_transactions( [&](){
return db.with_write_lock( [&](){
......@@ -122,6 +173,7 @@ struct controller_impl {
});
}
block_state_ptr push_block_impl( const signed_block_ptr& b ) {
auto head_state = fork_db.add( b );
......@@ -149,7 +201,8 @@ struct controller_impl {
// pop all blocks from the bad fork
while( head_block_id() != branches.second.back()->header.previous )
pop_block();
// re-apply good blocks
for( auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr ) {
apply_block( (*ritr) );
}
......@@ -167,6 +220,7 @@ struct controller_impl {
fork_db.set_validity( head_state, false );
throw;
}
return head;
} /// push_block_impl
bool should_enforce_runtime_limits()const {
......@@ -185,6 +239,7 @@ struct controller_impl {
{ try {
const auto& b = trace.block;
/* TODO RESTORE
update_global_properties( b );
update_global_dynamic_data( b );
update_signing_producer(signing_producer, b);
......@@ -193,18 +248,21 @@ struct controller_impl {
clear_expired_transactions();
update_last_irreversible_block();
resource_limits.process_account_limit_updates();
const auto& chain_config = self.get_global_properties().configuration;
_resource_limits.set_block_parameters(
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}}
);
*/
} FC_CAPTURE_AND_RETHROW() }
void clear_expired_transactions() {
//Look for expired transactions in the deduplication list, and remove them.
auto& transaction_idx = _db.get_mutable_index<transaction_multi_index>();
auto& transaction_idx = db.get_mutable_index<transaction_multi_index>();
const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
while( (!dedupe_index.empty()) && (head_block_time() > fc::time_point(dedupe_index.begin()->expiration) ) ) {
transaction_idx.remove(*dedupe_index.begin());
......@@ -212,10 +270,10 @@ struct controller_impl {
// Look for expired transactions in the pending generated list, and remove them.
// TODO: expire these by sending error to handler
auto& generated_transaction_idx = _db.get_mutable_index<generated_transaction_multi_index>();
auto& generated_transaction_idx = db.get_mutable_index<generated_transaction_multi_index>();
const auto& generated_index = generated_transaction_idx.indices().get<by_expiration>();
while( (!generated_index.empty()) && (head_block_time() > generated_index.begin()->expiration) ) {
_destroy_generated_transaction(*generated_index.begin());
// TODO: destroy_generated_transaction(*generated_index.begin());
}
}
......@@ -224,7 +282,7 @@ struct controller_impl {
void validate_tapos( const transaction& trx )const {
if( !should_check_tapos() ) return;
const auto& tapos_block_summary = _db.get<block_summary_object>((uint16_t)trx.ref_block_num);
const auto& tapos_block_summary = db.get<block_summary_object>((uint16_t)trx.ref_block_num);
//Verify TaPoS block summary has correct ID prefix, and that this block's time is not past the expiration
EOS_ASSERT(trx.verify_reference_block(tapos_block_summary.block_id), invalid_ref_block_exception,
......@@ -232,12 +290,44 @@ struct controller_impl {
("tapos_summary", tapos_block_summary));
}
/**
* At the start of each block we notify the system contract with a transaction that passes in
* the block header of the prior block (which is currently our head block)
*/
transaction get_on_block_transaction()
{
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}};
on_block_act.data = fc::raw::pack(head_block_header());
transaction trx;
trx.actions.emplace_back(std::move(on_block_act));
trx.set_reference_block(head_block_id());
trx.expiration = head_block_time() + fc::seconds(1);
return trx;
}
/**
* apply_block
*
* This method starts an undo session, whose revision number should match
* the block number.
*
* It first does some parallel read-only sanity checks on all input transactions.
*
* It then follows the transaction delivery schedule defined by the block_summary.
*
*/
void apply_block( block_state_ptr bstate ) {
auto session = _db.start_undo_session(true);
auto session = db.start_undo_session(true);
optional<fc::time_point> processing_deadline;
if( should_enforce_runtime_limits() ) {
processing_deadline = fc::time_point::now() + cfg.limits.max_push_block_us;
processing_deadline = fc::time_point::now() + conf.limits.max_push_block_us;
}
auto& next_block_trace = bstate->trace;
......@@ -251,22 +341,22 @@ struct controller_impl {
validate_net_usage( trx, item.second->billable_packed_size );
}
for( uint32_t region_index = 0; region_index < next_block.regions.size(); ++region_index ) {
apply_region( region_index, next_block_trace, bstate->block.regions[region_index] );
for( uint32_t region_index = 0; region_index < bstate->block->regions.size(); ++region_index ) {
apply_region( region_index, *bstate );
}
FC_ASSERT( bstate->header.action_mroot == next_block_trace.calculate_action_merkle_root(),
"action merkle root does not match" );
finalize_block( *next_block_trace );
"action merkle root does not match" ); finalize_block( *next_block_trace );
fork_db.set_validity( bstate, true );
applied_block( next_block_trace ); /// emit signal to plugins before exiting undo state
self.applied_block( next_block_trace ); /// emit signal to plugins before exiting undo state
session.push();
head = move(bstate);
} /// apply_block
void apply_region( uint32_t region_index, block_trace& b_trace, const block_state& bstate ) {
void apply_region( uint32_t region_index, const block_state& bstate ) {
const auto& r = bstate.block->regions[region_index];
EOS_ASSERT(!r.cycles_summary.empty(), tx_empty_region,"region[${r_index}] has no cycles", ("r_index",region_index));
......
......@@ -21,11 +21,10 @@ struct block_header_state {
flat_map<account_name,uint32_t> producer_to_last_produced;
block_header_state next( const signed_block_header& h )const;
uint32_t calc_dpos_last_irreversible()const;
bool is_active_producer( account_name n )const;
producer_key scheduled_producer( block_timestamp_type t )const;
bool is_start_of_round( uint32_t block_num )const;
uint32_t blocks_per_round()const;
};
......
......@@ -13,6 +13,8 @@ namespace eosio { namespace chain {
map<transaction_id_type,transaction_metadata_ptr> input_transactions;
bool validated = false;
block_trace_ptr trace;
void reset_trace();
};
typedef std::shared_ptr<block_state> block_state_ptr;
......
#pragma once
#include <eosio/chain/block_state.hpp>
#include <eosio/chain/genesis_state.hpp>
#include <boost/signals2/signal.hpp>
namespace chainbase {
class database;
......@@ -8,6 +11,7 @@ namespace eosio { namespace chain {
struct controller_impl;
using chainbase::database;
using boost::signals2::signal;
class controller {
public:
......@@ -18,14 +22,14 @@ namespace eosio { namespace chain {
fc::microseconds max_deferred_transactions_us = fc::microseconds(-1);
};
path block_log_dir = config::default_block_log_dir;
path shared_memory_dir = config::default_shared_memory_dir;
uint64_t shared_memory_size = config::default_shared_memory_size;
path block_log_dir = chain::config::default_block_log_dir;
path shared_memory_dir = chain::config::default_shared_memory_dir;
uint64_t shared_memory_size = chain::config::default_shared_memory_size;
bool read_only = false;
contracts::genesis_state_type genesis;
genesis_state genesis;
runtime_limits limits;
wasm_interface::vm_type wasm_runtime = config::default_wasm_runtime;
wasm_interface::vm_type wasm_runtime = chain::config::default_wasm_runtime;
};
......@@ -39,7 +43,7 @@ namespace eosio { namespace chain {
* be pushed.
*/
void start_block( block_timestamp_type time );
void finalize_block( signing_lambda );
// void finalize_block( signing_lambda );
block_state_ptr push_block( const signed_block_ptr& b );
transaction_trace push_transaction( const signed_transaction& t );
......@@ -49,7 +53,7 @@ namespace eosio { namespace chain {
uint32_t head_block_num();
signal<void(const block_trace&)> applied_block;
signal<void(const block_trace_ptr&)> applied_block;
signal<void(const signed_block&)> applied_irreversible_block;
private:
......@@ -58,3 +62,10 @@ namespace eosio { namespace chain {
};
} } /// eosio::chain
FC_REFLECT( eosio::chain::controller::config,
(block_log_dir)
(shared_memory_dir)(shared_memory_size)(read_only)
(genesis)
(limits)(wasm_runtime)
)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册