提交 8fe840b7 编写于 作者: K Kayan

Merge branch 'release/1.1' into delegatebw_buyram

......@@ -59,6 +59,7 @@ struct controller_impl {
bool replaying = false;
db_read_mode read_mode = db_read_mode::SPECULATIVE;
bool in_trx_requiring_checks = false; ///< if true, checks that are normally skipped on replay (e.g. auth checks) cannot be skipped
optional<fc::microseconds> subjective_cpu_leeway;
typedef pair<scope_name,action_name> handler_key;
map< account_name, map<handler_key, apply_handler> > apply_handlers;
......@@ -516,6 +517,7 @@ struct controller_impl {
auto code = e.code();
return (code == subjective_block_production_exception::code_value)
|| (code == block_net_usage_exceeded::code_value)
|| (code == greylist_net_usage_exceeded::code_value)
|| (code == block_cpu_usage_exceeded::code_value)
|| (code == deadline_exception::code_value)
|| (code == leeway_deadline_exception::code_value)
......@@ -654,13 +656,16 @@ struct controller_impl {
transaction_trace_ptr push_transaction( const transaction_metadata_ptr& trx,
fc::time_point deadline,
bool implicit,
uint32_t billed_cpu_time_us )
uint32_t billed_cpu_time_us)
{
EOS_ASSERT(deadline != fc::time_point(), transaction_exception, "deadline cannot be uninitialized");
transaction_trace_ptr trace;
try {
transaction_context trx_context(self, trx->trx, trx->id);
if ((bool)subjective_cpu_leeway && pending->_block_status == controller::block_status::incomplete) {
trx_context.leeway = *subjective_cpu_leeway;
}
trx_context.deadline = deadline;
trx_context.billed_cpu_time_us = billed_cpu_time_us;
trace = trx_context.trace;
......@@ -671,7 +676,7 @@ struct controller_impl {
} else {
trx_context.init_for_input_trx( trx->packed_trx.get_unprunable_size(),
trx->packed_trx.get_prunable_size(),
trx->trx.signatures.size() );
trx->trx.signatures.size());
}
if( trx_context.can_subjectively_fail && pending->_block_status == controller::block_status::incomplete ) {
......@@ -693,7 +698,6 @@ struct controller_impl {
false
);
}
trx_context.exec();
trx_context.finalize(); // Automatically rounds up network and CPU usage in trace and bills payers if successful
......@@ -840,7 +844,7 @@ struct controller_impl {
if( receipt.trx.contains<packed_transaction>() ) {
auto& pt = receipt.trx.get<packed_transaction>();
auto mtrx = std::make_shared<transaction_metadata>(pt);
trace = push_transaction( mtrx, fc::time_point::maximum(), false, receipt.cpu_usage_us );
trace = push_transaction( mtrx, fc::time_point::maximum(), false, receipt.cpu_usage_us);
} else if( receipt.trx.contains<transaction_id_type>() ) {
trace = push_scheduled_transaction( receipt.trx.get<transaction_id_type>(), fc::time_point::maximum(), receipt.cpu_usage_us );
} else {
......@@ -1608,5 +1612,24 @@ bool controller::is_known_unexpired_transaction( const transaction_id_type& id)
return db().find<transaction_object, by_trx_id>(id);
}
void controller::set_subjective_cpu_leeway(fc::microseconds leeway) {
my->subjective_cpu_leeway = leeway;
}
void controller::add_resource_greylist(const account_name &name) {
my->conf.resource_greylist.insert(name);
}
void controller::remove_resource_greylist(const account_name &name) {
my->conf.resource_greylist.erase(name);
}
bool controller::is_resource_greylisted(const account_name &name) const {
return my->conf.resource_greylist.find(name) != my->conf.resource_greylist.end();
}
const flat_set<account_name> &controller::get_resource_greylist() const {
return my->conf.resource_greylist;
}
} } /// eosio::chain
......@@ -61,6 +61,8 @@ namespace eosio { namespace chain {
wasm_interface::vm_type wasm_runtime = chain::config::default_wasm_runtime;
db_read_mode read_mode = db_read_mode::SPECULATIVE;
flat_set<account_name> resource_greylist;
};
enum class block_status {
......@@ -178,7 +180,10 @@ namespace eosio { namespace chain {
void check_key_list( const public_key_type& key )const;
bool is_producing_block()const;
void add_resource_greylist(const account_name &name);
void remove_resource_greylist(const account_name &name);
bool is_resource_greylisted(const account_name &name) const;
const flat_set<account_name> &get_resource_greylist() const;
void validate_referenced_accounts( const transaction& t )const;
void validate_expiration( const transaction& t )const;
......@@ -196,6 +201,8 @@ namespace eosio { namespace chain {
db_read_mode get_read_mode()const;
void set_subjective_cpu_leeway(fc::microseconds leeway);
signal<void(const signed_block_ptr&)> pre_accepted_block;
signal<void(const block_state_ptr&)> accepted_block_header;
signal<void(const block_state_ptr&)> accepted_block;
......@@ -262,4 +269,5 @@ FC_REFLECT( eosio::chain::controller::config,
(contracts_console)
(genesis)
(wasm_runtime)
(resource_greylist)
)
......@@ -158,8 +158,8 @@ namespace eosio { namespace chain {
3030008, "Block is not signed with expected key" )
FC_DECLARE_DERIVED_EXCEPTION( wrong_producer, block_validate_exception,
3030009, "Block is not signed by expected producer" )
FC_DECLARE_DERIVED_EXCEPTION( transaction_exception, chain_exception,
......@@ -228,7 +228,7 @@ namespace eosio { namespace chain {
3060003, "Contract Table Query Exception" )
FC_DECLARE_DERIVED_EXCEPTION( contract_query_exception, database_exception,
3060004, "Contract Query Exception" )
FC_DECLARE_DERIVED_EXCEPTION( wasm_exception, chain_exception,
3070000, "WASM Exception" )
FC_DECLARE_DERIVED_EXCEPTION( page_memory_error, wasm_exception,
......@@ -258,6 +258,8 @@ namespace eosio { namespace chain {
3080005, "Transaction CPU usage is too much for the remaining allowable usage of the current block" )
FC_DECLARE_DERIVED_EXCEPTION( deadline_exception, resource_exhausted_exception,
3080006, "Transaction took too long" )
FC_DECLARE_DERIVED_EXCEPTION( greylist_net_usage_exceeded, resource_exhausted_exception,
3080007, "Transaction exceeded the current greylisted account network usage limit" )
FC_DECLARE_DERIVED_EXCEPTION( leeway_deadline_exception, deadline_exception,
3081001, "Transaction reached the deadline set due to leeway on account CPU limits" )
......@@ -285,23 +287,25 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( misc_exception, chain_exception,
3100000, "Miscellaneous exception" )
FC_DECLARE_DERIVED_EXCEPTION( rate_limiting_state_inconsistent, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( rate_limiting_state_inconsistent, misc_exception,
3100001, "Internal state is no longer consistent" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, misc_exception,
3100002, "Unknown block" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_transaction_exception, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( unknown_transaction_exception, misc_exception,
3100003, "Unknown transaction" )
FC_DECLARE_DERIVED_EXCEPTION( fixed_reversible_db_exception, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( fixed_reversible_db_exception, misc_exception,
3100004, "Corrupted reversible block database was fixed" )
FC_DECLARE_DERIVED_EXCEPTION( extract_genesis_state_exception, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( extract_genesis_state_exception, misc_exception,
3100005, "Extracted genesis state from blocks.log" )
FC_DECLARE_DERIVED_EXCEPTION( subjective_block_production_exception, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( subjective_block_production_exception, misc_exception,
3100006, "Subjective exception thrown during block production" )
FC_DECLARE_DERIVED_EXCEPTION( multiple_voter_info, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( multiple_voter_info, misc_exception,
3100007, "Multiple voter info detected" )
FC_DECLARE_DERIVED_EXCEPTION( unsupported_feature, misc_exception,
FC_DECLARE_DERIVED_EXCEPTION( unsupported_feature, misc_exception,
3100008, "Feature is currently unsupported" )
FC_DECLARE_DERIVED_EXCEPTION( node_management_success, misc_exception,
3100009, "Node management operation successfully executed" )
FC_DECLARE_DERIVED_EXCEPTION( plugin_exception, chain_exception,
......@@ -348,7 +352,7 @@ namespace eosio { namespace chain {
3120011, "Wallet lock timeout is invalid" )
FC_DECLARE_DERIVED_EXCEPTION( secure_enclave_exception, wallet_exception,
3120012, "Secure Enclave Exception" )
FC_DECLARE_DERIVED_EXCEPTION( whitelist_blacklist_exception, chain_exception,
3130000, "Actor or contract whitelist/blacklist exception" )
......@@ -373,7 +377,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( abi_exception, chain_exception,
3015000, "ABI exception" )
3015000, "ABI exception" )
FC_DECLARE_DERIVED_EXCEPTION( abi_not_found_exception, abi_exception,
3015001, "No ABI found" )
FC_DECLARE_DERIVED_EXCEPTION( invalid_ricardian_clause_exception, abi_exception,
......@@ -395,13 +399,13 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( abi_serialization_deadline_exception, abi_exception,
3015010, "ABI serialization time has exceeded the deadline" )
FC_DECLARE_DERIVED_EXCEPTION( abi_recursion_depth_exception, abi_exception,
3015011, "ABI recursive definition has exceeded the max recursion depth" )
3015011, "ABI recursive definition has exceeded the max recursion depth" )
FC_DECLARE_DERIVED_EXCEPTION( abi_circular_def_exception, abi_exception,
3015012, "Circular definition is detected in the ABI" )
3015012, "Circular definition is detected in the ABI" )
FC_DECLARE_DERIVED_EXCEPTION( unpack_exception, abi_exception,
3015013, "Unpack data exception" )
3015013, "Unpack data exception" )
FC_DECLARE_DERIVED_EXCEPTION( pack_exception, abi_exception,
3015014, "Pack data exception" )
3015014, "Pack data exception" )
FC_DECLARE_DERIVED_EXCEPTION( contract_exception, chain_exception,
3160000, "Contract exception" )
......@@ -446,7 +450,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( reversible_blocks_backup_dir_exist, reversible_blocks_exception,
3180002, "Backup directory for reversible blocks already existg" )
FC_DECLARE_DERIVED_EXCEPTION( gap_in_reversible_blocks_db, reversible_blocks_exception,
3180003, "There is gap in reversible blocks database" )
3180003, "Gap in the reversible blocks database" )
FC_DECLARE_DERIVED_EXCEPTION( block_log_exception, chain_exception,
3190000, "Block log exception" )
......@@ -474,7 +478,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( resource_limit_exception, chain_exception,
3210000, "Resource limit exception" )
FC_DECLARE_DERIVED_EXCEPTION( mongo_db_exception, chain_exception,
3220000, "Mongo DB exception" )
FC_DECLARE_DERIVED_EXCEPTION( mongo_db_insert_fail, mongo_db_exception,
......
......@@ -2,6 +2,7 @@
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/types.hpp>
#include <chainbase/chainbase.hpp>
#include <set>
namespace eosio { namespace chain { namespace resource_limits {
namespace impl {
......@@ -65,11 +66,11 @@ namespace eosio { namespace chain { namespace resource_limits {
uint64_t get_block_cpu_limit() const;
uint64_t get_block_net_limit() const;
int64_t get_account_cpu_limit( const account_name& name ) const;
int64_t get_account_net_limit( const account_name& name ) const;
int64_t get_account_cpu_limit( const account_name& name, bool elastic = true) const;
int64_t get_account_net_limit( const account_name& name, bool elastic = true) const;
account_resource_limit get_account_cpu_limit_ex( const account_name& name ) const;
account_resource_limit get_account_net_limit_ex( const account_name& name ) const;
account_resource_limit get_account_cpu_limit_ex( const account_name& name, bool elastic = true) const;
account_resource_limit get_account_net_limit_ex( const account_name& name, bool elastic = true) const;
int64_t get_account_ram_usage( const account_name& name ) const;
......
......@@ -6,7 +6,7 @@ namespace eosio { namespace chain {
class transaction_context {
private:
void init( uint64_t initial_net_usage );
void init( uint64_t initial_net_usage);
public:
......@@ -19,7 +19,7 @@ namespace eosio { namespace chain {
void init_for_input_trx( uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_prunable_size,
uint32_t num_signatures );
uint32_t num_signatures);
void init_for_deferred_trx( fc::time_point published );
......@@ -88,6 +88,7 @@ namespace eosio { namespace chain {
uint64_t net_limit = 0;
bool net_limit_due_to_block = true;
bool net_limit_due_to_greylist = false;
uint64_t eager_net_limit = 0;
uint64_t& net_usage; /// reference to trace->net_usage
......
......@@ -334,12 +334,12 @@ uint64_t resource_limits_manager::get_block_net_limit() const {
return config.net_limit_parameters.max - state.pending_net_usage;
}
int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name ) const {
auto arl = get_account_cpu_limit_ex(name);
int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name, bool elastic ) const {
auto arl = get_account_cpu_limit_ex(name, elastic);
return arl.available;
}
account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const account_name& name ) const {
account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, bool elastic) const {
const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name);
......@@ -356,7 +356,7 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const
uint128_t window_size = config.account_cpu_usage_average_window;
uint128_t virtual_cpu_capacity_in_window = (uint128_t)state.virtual_cpu_limit * window_size;
uint128_t virtual_cpu_capacity_in_window = (uint128_t)(elastic ? state.virtual_cpu_limit : config.cpu_limit_parameters.max) * window_size;
uint128_t user_weight = (uint128_t)cpu_weight;
uint128_t all_user_weight = (uint128_t)state.total_cpu_weight;
......@@ -373,12 +373,12 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const
return arl;
}
int64_t resource_limits_manager::get_account_net_limit( const account_name& name ) const {
auto arl = get_account_net_limit_ex(name);
int64_t resource_limits_manager::get_account_net_limit( const account_name& name, bool elastic) const {
auto arl = get_account_net_limit_ex(name, elastic);
return arl.available;
}
account_resource_limit resource_limits_manager::get_account_net_limit_ex( const account_name& name ) const {
account_resource_limit resource_limits_manager::get_account_net_limit_ex( const account_name& name, bool elastic) const {
const auto& config = _db.get<resource_limits_config_object>();
const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name);
......@@ -394,7 +394,7 @@ account_resource_limit resource_limits_manager::get_account_net_limit_ex( const
uint128_t window_size = config.account_net_usage_average_window;
uint128_t virtual_network_capacity_in_window = state.virtual_net_limit * window_size;
uint128_t virtual_network_capacity_in_window = (uint128_t)(elastic ? state.virtual_net_limit : config.net_limit_parameters.max) * window_size;
uint128_t user_weight = (uint128_t)net_weight;
uint128_t all_user_weight = (uint128_t)state.total_net_weight;
......@@ -412,5 +412,4 @@ account_resource_limit resource_limits_manager::get_account_net_limit_ex( const
return arl;
}
} } } /// eosio::chain::resource_limits
......@@ -27,7 +27,7 @@ namespace eosio { namespace chain {
EOS_ASSERT( trx.transaction_extensions.size() == 0, unsupported_feature, "we don't support any extensions yet" );
}
void transaction_context::init(uint64_t initial_net_usage )
void transaction_context::init(uint64_t initial_net_usage)
{
EOS_ASSERT( !is_initialized, transaction_exception, "cannot initialize twice" );
const static int64_t large_number_no_overflow = std::numeric_limits<int64_t>::max()/2;
......@@ -88,10 +88,11 @@ namespace eosio { namespace chain {
int64_t account_net_limit = large_number_no_overflow;
int64_t account_cpu_limit = large_number_no_overflow;
for( const auto& a : bill_to_accounts ) {
auto net_limit = rl.get_account_net_limit(a);
bool elastic = !(control.is_producing_block() && control.is_resource_greylisted(a));
auto net_limit = rl.get_account_net_limit(a, elastic);
if( net_limit >= 0 )
account_net_limit = std::min( account_net_limit, net_limit );
auto cpu_limit = rl.get_account_cpu_limit(a);
auto cpu_limit = rl.get_account_cpu_limit(a, elastic);
if( cpu_limit >= 0 )
account_cpu_limit = std::min( account_cpu_limit, cpu_limit );
}
......@@ -134,12 +135,12 @@ namespace eosio { namespace chain {
void transaction_context::init_for_implicit_trx( uint64_t initial_net_usage )
{
published = control.pending_block_time();
init( initial_net_usage );
init( initial_net_usage);
}
void transaction_context::init_for_input_trx( uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_prunable_size,
uint32_t num_signatures )
uint32_t num_signatures)
{
const auto& cfg = control.get_global_properties().configuration;
......@@ -168,7 +169,7 @@ namespace eosio { namespace chain {
control.validate_expiration( trx );
control.validate_tapos( trx );
control.validate_referenced_accounts( trx );
init( initial_net_usage );
init( initial_net_usage);
record_transaction( id, trx.expiration ); /// checks for dupes
}
......@@ -222,10 +223,13 @@ namespace eosio { namespace chain {
int64_t account_net_limit = large_number_no_overflow;
int64_t account_cpu_limit = large_number_no_overflow;
for( const auto& a : bill_to_accounts ) {
auto net_limit = rl.get_account_net_limit(a);
if( net_limit >= 0 )
bool elastic = !(control.is_producing_block() && control.is_resource_greylisted(a));
auto net_limit = rl.get_account_net_limit(a, elastic);
if( net_limit >= 0 ) {
account_net_limit = std::min( account_net_limit, net_limit );
auto cpu_limit = rl.get_account_cpu_limit(a);
if (!elastic) net_limit_due_to_greylist = true;
}
auto cpu_limit = rl.get_account_cpu_limit(a, elastic);
if( cpu_limit >= 0 )
account_cpu_limit = std::min( account_cpu_limit, cpu_limit );
}
......@@ -271,10 +275,14 @@ namespace eosio { namespace chain {
void transaction_context::check_net_usage()const {
if( BOOST_UNLIKELY(net_usage > eager_net_limit) ) {
if( net_limit_due_to_block ) {
if ( net_limit_due_to_block ) {
EOS_THROW( block_net_usage_exceeded,
"not enough space left in block: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
} else if (net_limit_due_to_greylist) {
EOS_THROW( greylist_net_usage_exceeded,
"net usage of transaction is too high: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
} else {
EOS_THROW( tx_net_usage_exceeded,
"net usage of transaction is too high: ${net_usage} > ${net_limit}",
......
......@@ -233,6 +233,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
"stop hard replay / block log recovery at this block number (if set to non-zero number)")
("import-reversible-blocks", bpo::value<bfs::path>(),
"replace reversible block database with blocks imported from specified file and then exit")
("export-reversible-blocks", bpo::value<bfs::path>(),
"export reversible block database in portable format into specified file and then exit")
;
}
......@@ -379,6 +381,21 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
EOS_THROW( extract_genesis_state_exception, "extracted genesis state from blocks.log" );
}
if( options.count("export-reversible-blocks") ) {
auto p = options.at( "export-reversible-blocks" ).as<bfs::path>();
if( p.is_relative()) {
p = bfs::current_path() / p;
}
if( export_reversible_blocks( my->chain_config->blocks_dir/config::reversible_blocks_dir_name, p ) )
ilog( "Saved all blocks from reversible block database into '${path}'", ("path", p.generic_string()) );
else
ilog( "Saved recovered blocks from reversible block database into '${path}'", ("path", p.generic_string()) );
EOS_THROW( node_management_success, "exported reversible blocks" );
}
if( options.at( "delete-all-blocks" ).as<bool>()) {
ilog( "Deleting state database and blocks" );
if( options.at( "truncate-at-block" ).as<uint32_t>() > 0 )
......@@ -436,7 +453,7 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
import_reversible_blocks( my->chain_config->blocks_dir/config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size, reversible_blocks_file );
EOS_THROW( fixed_reversible_db_exception, "imported reversible blocks" );
EOS_THROW( node_management_success, "imported reversible blocks" );
}
if( options.count("import-reversible-blocks") ) {
......@@ -598,7 +615,7 @@ bool chain_plugin::block_is_on_preferred_chain(const block_id_type& block_id) {
}
bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t cache_size,
optional<fc::path> new_db_dir, uint32_t truncate_at_block )const {
optional<fc::path> new_db_dir, uint32_t truncate_at_block ) {
try {
chainbase::database reversible( db_dir, database::read_only); // Test if dirty
// If it reaches here, then the reversible database is not dirty
......@@ -651,26 +668,29 @@ bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t c
chainbase::database new_reversible( reversible_dir, database::read_write, cache_size );
std::fstream reversible_blocks;
reversible_blocks.open( (reversible_dir.parent_path() / std::string("portable-reversible-blocks-").append( now ) ).generic_string().c_str(),
std::ios::out | std::ios::binary | std::ios::app );
std::ios::out | std::ios::binary );
uint32_t num = 0;
uint32_t start = 0;
uint32_t end = 0;
old_reversible.add_index<reversible_block_index>();
new_reversible.add_index<reversible_block_index>();
const auto& ubi = old_reversible.get_index<reversible_block_index,by_num>();
auto itr = ubi.begin();
if( itr != ubi.end() ) {
start = itr->blocknum;
end = start - 1;
}
if( truncate_at_block > 0 && start > truncate_at_block ) {
ilog( "Did not recover any reversible blocks since the specified block number to stop at (${stop}) is less than first block in the reversible database (${start}).", ("stop", truncate_at_block)("start", start) );
return true;
}
try {
old_reversible.add_index<reversible_block_index>();
new_reversible.add_index<reversible_block_index>();
const auto& ubi = old_reversible.get_index<reversible_block_index,by_num>();
auto itr = ubi.begin();
if( itr != ubi.end() ) {
start = itr->blocknum;
end = start - 1;
}
if( truncate_at_block > 0 && start > truncate_at_block ) {
ilog( "Did not recover any reversible blocks since the specified block number to stop at (${stop}) is less than first block in the reversible database (${start}).", ("stop", truncate_at_block)("start", start) );
return true;
}
for( ; itr != ubi.end(); ++itr ) {
EOS_ASSERT( itr->blocknum == end + 1, gap_in_reversible_blocks_db, "gap in reversible block database" );
EOS_ASSERT( itr->blocknum == end + 1, gap_in_reversible_blocks_db,
"gap in reversible block database between ${end} and ${blocknum}",
("end", end)("blocknum", itr->blocknum)
);
reversible_blocks.write( itr->packedblock.data(), itr->packedblock.size() );
new_reversible.create<reversible_block_object>( [&]( auto& ubo ) {
ubo.blocknum = itr->blocknum;
......@@ -681,6 +701,8 @@ bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t c
if( end == truncate_at_block )
break;
}
} catch( const gap_in_reversible_blocks_db& e ) {
wlog( "${details}", ("details", e.to_detail_string()) );
} catch( ... ) {}
if( end == truncate_at_block )
......@@ -699,7 +721,7 @@ bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t c
bool chain_plugin::import_reversible_blocks( const fc::path& reversible_dir,
uint32_t cache_size,
const fc::path& reversible_blocks_file )const {
const fc::path& reversible_blocks_file ) {
std::fstream reversible_blocks;
chainbase::database new_reversible( reversible_dir, database::read_write, cache_size );
reversible_blocks.open( reversible_blocks_file.generic_string().c_str(), std::ios::in | std::ios::binary );
......@@ -711,8 +733,8 @@ bool chain_plugin::import_reversible_blocks( const fc::path& reversible_dir,
uint32_t num = 0;
uint32_t start = 0;
uint32_t end = 0;
new_reversible.add_index<reversible_block_index>();
try {
new_reversible.add_index<reversible_block_index>();
while( reversible_blocks.tellg() < end_pos ) {
signed_block tmp;
fc::raw::unpack(reversible_blocks, tmp);
......@@ -721,7 +743,10 @@ bool chain_plugin::import_reversible_blocks( const fc::path& reversible_dir,
if( start == 0 ) {
start = num;
} else {
EOS_ASSERT( num == end + 1, gap_in_reversible_blocks_db, "gap in reversible block database" );
EOS_ASSERT( num == end + 1, gap_in_reversible_blocks_db,
"gap in reversible block database between ${end} and ${num}",
("end", end)("num", num)
);
}
new_reversible.create<reversible_block_object>( [&]( auto& ubo ) {
......@@ -730,6 +755,9 @@ bool chain_plugin::import_reversible_blocks( const fc::path& reversible_dir,
});
end = num;
}
} catch( gap_in_reversible_blocks_db& e ) {
wlog( "${details}", ("details", e.to_detail_string()) );
FC_RETHROW_EXCEPTION( e, warn, "rethrow" );
} catch( ... ) {}
ilog( "Imported blocks ${start} to ${end}", ("start", start)("end", end));
......@@ -740,6 +768,52 @@ bool chain_plugin::import_reversible_blocks( const fc::path& reversible_dir,
return true;
}
bool chain_plugin::export_reversible_blocks( const fc::path& reversible_dir,
const fc::path& reversible_blocks_file ) {
chainbase::database reversible( reversible_dir, database::read_only, 0, true );
std::fstream reversible_blocks;
reversible_blocks.open( reversible_blocks_file.generic_string().c_str(), std::ios::out | std::ios::binary );
uint32_t num = 0;
uint32_t start = 0;
uint32_t end = 0;
reversible.add_index<reversible_block_index>();
const auto& ubi = reversible.get_index<reversible_block_index,by_num>();
auto itr = ubi.begin();
if( itr != ubi.end() ) {
start = itr->blocknum;
end = start - 1;
}
try {
for( ; itr != ubi.end(); ++itr ) {
EOS_ASSERT( itr->blocknum == end + 1, gap_in_reversible_blocks_db,
"gap in reversible block database between ${end} and ${blocknum}",
("end", end)("blocknum", itr->blocknum)
);
signed_block tmp;
fc::datastream<const char *> ds( itr->packedblock.data(), itr->packedblock.size() );
fc::raw::unpack(ds, tmp); // Verify that packed block has not been corrupted.
reversible_blocks.write( itr->packedblock.data(), itr->packedblock.size() );
end = itr->blocknum;
++num;
}
} catch( const gap_in_reversible_blocks_db& e ) {
wlog( "${details}", ("details", e.to_detail_string()) );
} catch( ... ) {}
if( num == 0 ) {
ilog( "There were no recoverable blocks in the reversible block database" );
return false;
}
else if( num == 1 )
ilog( "Exported 1 block from reversible block database: block ${start}", ("start", start) );
else
ilog( "Exported ${num} blocks from reversible block database: blocks ${start} to ${end}",
("num", num)("start", start)("end", end) );
return (end >= start) && ((end - start + 1) == num);
}
controller::config& chain_plugin::chain_config() {
// will trigger optional assert if called before/after plugin_initialize()
return *my->chain_config;
......@@ -1342,8 +1416,9 @@ read_only::get_account_results read_only::get_account( const get_account_params&
result.last_code_update = a.last_code_update;
result.created = a.creation_date;
result.net_limit = rm.get_account_net_limit_ex( result.account_name );
result.cpu_limit = rm.get_account_cpu_limit_ex( result.account_name );
bool grelisted = db.is_resource_greylisted(result.account_name);
result.net_limit = rm.get_account_net_limit_ex( result.account_name, !grelisted);
result.cpu_limit = rm.get_account_cpu_limit_ex( result.account_name, !grelisted);
result.ram_usage = rm.get_account_ram_usage( result.account_name );
const auto& permissions = d.get_index<permission_index,by_owner>();
......
......@@ -504,17 +504,21 @@ public:
bool block_is_on_preferred_chain(const chain::block_id_type& block_id);
bool recover_reversible_blocks( const fc::path& db_dir,
uint32_t cache_size,
optional<fc::path> new_db_dir = optional<fc::path>(),
uint32_t truncate_at_block = 0
)const;
bool import_reversible_blocks( const fc::path& reversible_dir,
uint32_t cache_size,
const fc::path& reversible_blocks_file
)const;
static bool recover_reversible_blocks( const fc::path& db_dir,
uint32_t cache_size,
optional<fc::path> new_db_dir = optional<fc::path>(),
uint32_t truncate_at_block = 0
);
static bool import_reversible_blocks( const fc::path& reversible_dir,
uint32_t cache_size,
const fc::path& reversible_blocks_file
);
static bool export_reversible_blocks( const fc::path& reversible_dir,
const fc::path& reversible_blocks_file
);
// Only call this in plugin_initialize() to modify controller constructor configuration
controller::config& chain_config();
// Only call this after plugin_startup()!
......
......@@ -807,6 +807,10 @@ void mongo_db_plugin_impl::_process_accepted_block( const chain::block_state_ptr
using namespace bsoncxx::types;
using namespace bsoncxx::builder;
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;
mongocxx::options::update update_opts{};
update_opts.upsert( true );
auto block_num = bs->block_num;
const auto block_id = bs->id;
......@@ -843,7 +847,8 @@ void mongo_db_plugin_impl::_process_accepted_block( const chain::block_state_ptr
block_state_doc.append(kvp( "createdAt", b_date{now} ));
try {
if( !block_states.insert_one( block_state_doc.view())) {
if( !block_states.update_one( make_document( kvp( "block_id", block_id_str )),
make_document( kvp( "$set", block_state_doc.view())), update_opts )) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block_state ${bid}", ("bid", block_id));
}
} catch(...) {
......@@ -875,7 +880,8 @@ void mongo_db_plugin_impl::_process_accepted_block( const chain::block_state_ptr
block_doc.append(kvp( "createdAt", b_date{now} ));
try {
if( !blocks.insert_one( block_doc.view())) {
if( !blocks.update_one( make_document( kvp( "block_id", block_id_str )),
make_document( kvp( "$set", block_doc.view())), update_opts )) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block ${bid}", ("bid", block_id));
}
} catch(...) {
......
......@@ -76,6 +76,12 @@ void producer_api_plugin::plugin_startup() {
INVOKE_R_V(producer, get_runtime_options), 201),
CALL(producer, producer, update_runtime_options,
INVOKE_V_R(producer, update_runtime_options, producer_plugin::runtime_options), 201),
CALL(producer, producer, add_greylist_accounts,
INVOKE_V_R(producer, add_greylist_accounts, producer_plugin::greylist_params), 201),
CALL(producer, producer, remove_greylist_accounts,
INVOKE_V_R(producer, remove_greylist_accounts, producer_plugin::greylist_params), 201),
CALL(producer, producer, get_greylist,
INVOKE_R_V(producer, get_greylist), 201),
});
}
......
......@@ -23,6 +23,11 @@ public:
fc::optional<int32_t> max_irreversible_block_age;
fc::optional<int32_t> produce_time_offset_us;
fc::optional<int32_t> last_block_time_offset_us;
fc::optional<int32_t> subjective_cpu_leeway_us;
};
struct greylist_params {
std::vector<account_name> accounts;
};
producer_plugin();
......@@ -46,6 +51,10 @@ public:
void update_runtime_options(const runtime_options& options);
runtime_options get_runtime_options() const;
void add_greylist_accounts(const greylist_params& params);
void remove_greylist_accounts(const greylist_params& params);
greylist_params get_greylist() const;
signal<void(const chain::producer_confirmation&)> confirmed_block;
private:
std::shared_ptr<class producer_plugin_impl> my;
......@@ -53,4 +62,6 @@ private:
} //eosio
FC_REFLECT(eosio::producer_plugin::runtime_options, (max_transaction_time)(max_irreversible_block_age)(produce_time_offset_us)(last_block_time_offset_us));
FC_REFLECT(eosio::producer_plugin::runtime_options, (max_transaction_time)(max_irreversible_block_age)(produce_time_offset_us)(last_block_time_offset_us)(subjective_cpu_leeway_us));
FC_REFLECT(eosio::producer_plugin::greylist_params, (accounts));
......@@ -469,6 +469,8 @@ void producer_plugin::set_program_options(
" KEOSD:<data> \tis the URL where keosd is available and the approptiate wallet(s) are unlocked")
("keosd-provider-timeout", boost::program_options::value<int32_t>()->default_value(5),
"Limits the maximum time (in milliseconds) that is allowd for sending blocks to a keosd provider for signing")
("greylist-account", boost::program_options::value<vector<string>>()->composing()->multitoken(),
"account that can not access to extended CPU/NET virtual resources")
("produce-time-offset-us", boost::program_options::value<int32_t>()->default_value(0),
"offset of non last block producing time in micro second. Negative number results in blocks to go out sooner, and positive number results in blocks to go out later")
("last-block-time-offset-us", boost::program_options::value<int32_t>()->default_value(0),
......@@ -613,6 +615,15 @@ void producer_plugin::plugin_initialize(const boost::program_options::variables_
return my->on_incoming_transaction_async(trx, persist_until_expired, next );
});
if (options.count("greylist-account")) {
std::vector<std::string> greylist = options["greylist-account"].as<std::vector<std::string>>();
greylist_params param;
for (auto &a : greylist) {
param.accounts.push_back(account_name(a));
}
add_greylist_accounts(param);
}
} FC_LOG_AND_RETHROW() }
void producer_plugin::plugin_startup()
......@@ -710,6 +721,11 @@ void producer_plugin::update_runtime_options(const runtime_options& options) {
chain.abort_block();
my->schedule_production_loop();
}
if (options.subjective_cpu_leeway_us) {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
chain.set_subjective_cpu_leeway(fc::microseconds(*options.subjective_cpu_leeway_us));
}
}
producer_plugin::runtime_options producer_plugin::get_runtime_options() const {
......@@ -721,7 +737,30 @@ producer_plugin::runtime_options producer_plugin::get_runtime_options() const {
};
}
void producer_plugin::add_greylist_accounts(const greylist_params& params) {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
for (auto &acc : params.accounts) {
chain.add_resource_greylist(acc);
}
}
void producer_plugin::remove_greylist_accounts(const greylist_params& params) {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
for (auto &acc : params.accounts) {
chain.remove_resource_greylist(acc);
}
}
producer_plugin::greylist_params producer_plugin::get_greylist() const {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
greylist_params result;
const auto& list = chain.get_resource_greylist();
result.accounts.reserve(list.size());
for (auto &acc: list) {
result.accounts.push_back(acc);
}
return result;
}
optional<fc::time_point> producer_plugin_impl::calculate_next_block_time(const account_name& producer_name) const {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
......
......@@ -86,7 +86,8 @@ enum return_codes {
BAD_ALLOC = 1,
DATABASE_DIRTY = 2,
FIXED_REVERSIBLE = 3,
EXTRACTED_GENESIS = 4
EXTRACTED_GENESIS = 4,
NODE_MANAGEMENT_SUCCESS = 5
};
int main(int argc, char** argv)
......@@ -109,6 +110,8 @@ int main(int argc, char** argv)
return EXTRACTED_GENESIS;
} catch( const fixed_reversible_db_exception& e ) {
return FIXED_REVERSIBLE;
} catch( const node_management_success& e ) {
return NODE_MANAGEMENT_SUCCESS;
} catch( const fc::exception& e ) {
if( e.code() == fc::std_exception_code ) {
if( e.top_message().find( "database dirty flag set" ) != std::string::npos ) {
......
......@@ -36,6 +36,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sample-cluster-map.json ${CMAKE_CURRE
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/restart-scenarios-test.py ${CMAKE_CURRENT_BINARY_DIR}/restart-scenarios-test.py COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_run_test.py ${CMAKE_CURRENT_BINARY_DIR}/nodeos_run_test.py COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_run_remote_test.py ${CMAKE_CURRENT_BINARY_DIR}/nodeos_run_remote_test.py COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_voting_test.py ${CMAKE_CURRENT_BINARY_DIR}/nodeos_voting_test.py COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/consensus-validation-malicious-producers.py ${CMAKE_CURRENT_BINARY_DIR}/consensus-validation-malicious-producers.py COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/validate-dirty-db.py ${CMAKE_CURRENT_BINARY_DIR}/validate-dirty-db.py COPYONLY)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册