Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix overflow #691 #694

Merged
merged 4 commits into from
May 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 27 additions & 13 deletions libraries/chain/chaindb/cache_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ namespace cyberway { namespace chaindb {
}

if (object_ptr->has_cell()) {
object_ptr->mark_deleted();
object_ptr->release();
}
object_ptr.reset();
}
Expand Down Expand Up @@ -653,7 +653,9 @@ namespace cyberway { namespace chaindb {
service_tree_.erase(service_itr);
}

add_ram_usage(obj.cell(), -obj.service().size);
if (obj.has_cell()) {
add_ram_usage(obj.cell(), -obj.service().size);
}
}
}

Expand All @@ -669,24 +671,24 @@ namespace cyberway { namespace chaindb {
return false;
}

void change_cache_object(cache_object& obj, const int delta, cache_indicies& indicies) {
void change_cache_object(cache_object& obj, const int delta) {
add_ram_usage(obj.cell(), delta);

if (is_system_code(obj.service().code)) {
using state_object = eosio::chain::resource_limits::resource_limits_state_object;
if (obj.has_data() && obj.service().table == chaindb::tag<state_object>::get_code()) {
auto& state = multi_index_item_data<state_object>::get_T(obj);
ram_limit_ = get_ram_limit(state.virtual_limits[eosio::chain::resource_limits::RAM], state.reserved_ram_size);
ram_limit_ = get_ram_limit(state.ram_size, state.reserved_ram_size);
}

// don't rebuild indicies for interchain objects
if (indicies.capacity()) {
if (obj.indicies_.capacity()) {
return;
}
}

delete_cache_indicies(indicies);
build_cache_indicies(obj, indicies);
delete_cache_indicies(obj.indicies_);
build_cache_indicies(obj);
}

private:
Expand All @@ -712,10 +714,10 @@ namespace cyberway { namespace chaindb {
uint64_t ram_used_ = 0;

static uint64_t get_ram_limit(
const uint64_t limit = eosio::chain::config::default_virtual_ram_limit,
const uint64_t limit = eosio::chain::config::default_ram_size,
const uint64_t reserve = eosio::chain::config::default_reserved_ram_size
) {
// reserve for system objects (transactions, blocks, abi cache, ...)
// reserve for system objects (transactions, blocks, ...)
// and for pending caches (pending_cell_list_, ...)
return limit - reserve;
}
Expand Down Expand Up @@ -821,7 +823,7 @@ namespace cyberway { namespace chaindb {
return nullptr;
}

void build_cache_indicies(cache_object& obj, cache_indicies& indicies) {
void build_cache_indicies(cache_object& obj) {
auto& object = obj.object();
if (object.is_null()) return;

Expand All @@ -833,6 +835,7 @@ namespace cyberway { namespace chaindb {
auto ttr = abi.find_table(service.table);
if (!ttr) return;

auto& indicies = obj.indicies_;
indicies.reserve(ttr->indexes.size() - 1 /* skip primary */);
auto info = index_info(service.code, service.scope);
info.table = ttr;
Expand Down Expand Up @@ -920,6 +923,10 @@ namespace cyberway { namespace chaindb {
service.cache_object_cnt++;
}

if (is_new_ptr) {
build_cache_indicies(*obj_ptr.get());
}

return obj_ptr;
}

Expand Down Expand Up @@ -1029,7 +1036,7 @@ namespace cyberway { namespace chaindb {
blob_.clear();

if (has_cell()) {
map().change_cache_object(*this, delta, indicies_);
map().change_cache_object(*this, delta);
}
}

Expand All @@ -1054,9 +1061,16 @@ namespace cyberway { namespace chaindb {
}

void cache_object::release() {
auto& pending_state = pending_cache_object_state::cast(*state_);
pending_state.cell->map->release_cache_object(*this, indicies_, pending_state.is_deleted);
auto state = state_;
state_ = nullptr;

auto lru_state_ptr = lru_cache_object_state::cast(state);
if (lru_state_ptr) {
lru_state_ptr->cell->map->release_cache_object(*this, indicies_, false);
} else {
auto& pending_state = pending_cache_object_state::cast(*state);
pending_state.cell->map->release_cache_object(*this, indicies_, pending_state.is_deleted);
}
}

bool cache_object::is_deleted() const {
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/eosio_contract_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ abi_def eosio_contract_abi(abi_def eos_abi)
{"block_usage_accumulators", "usage_accumulator[]"},
{"pending_usage", "int64[]"},
{"virtual_limits", "uint64[]"},
{"ram_size", "uint64"},
{"reserved_ram_size", "uint64"}}
});

Expand Down
19 changes: 13 additions & 6 deletions libraries/chain/include/cyberway/chaindb/cache_item.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ namespace cyberway { namespace chaindb {
cache_data_ptr data_; // for interchain tables
cache_indicies indicies_;

private:
friend class cache_map_impl;
friend struct lru_cache_cell;
friend struct system_cache_cell;
friend struct pending_cache_cell;
friend struct pending_cache_object_state;

const cache_cell& cell() const;
cache_cell& cell();
cache_map_impl& map();
cache_object_state& state();
cache_object_state* swap_state(cache_object_state& state);

public:
cache_object() = default;
cache_object(cache_object&&) = default;
Expand All @@ -99,12 +112,6 @@ namespace cyberway { namespace chaindb {

bool is_deleted() const;

const cache_cell& cell() const;
cache_cell& cell();
cache_map_impl& map();
cache_object_state& state();
cache_object_state* swap_state(cache_object_state& state);

template <typename Request>
bool is_valid_table(const Request& request) const {
return
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/eosio/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const static auto default_state_dir_name = "state";
const static auto forkdb_filename = "forkdb.dat";
const static auto default_state_size = _GB;
const static auto default_state_guard_size = 128*_MB;
const static uint64_t default_virtual_ram_limit = 8*_GB;
const static uint64_t default_ram_size = 8*_GB;
const static uint64_t default_reserved_ram_size = 512*_MB;
const static uint64_t min_resource_usage_pct = percent_1 / 10;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ using namespace int_arithmetic;
uint64_t units = std::abs(units_signed);
bool neg = units_signed < 0;
// check for some numerical limits before doing any state mutations
EOS_ASSERT(units <= max_raw_value, rate_limiting_state_inconsistent, "Usage exceeds maximum value representable after extending for precision");
EOS_ASSERT(std::numeric_limits<decltype(consumed)>::max() - consumed >= units, rate_limiting_state_inconsistent, "Overflow in tracked usage when adding usage!");
EOS_ASSERT(neg || units <= max_raw_value, rate_limiting_state_inconsistent, "Usage exceeds maximum value representable after extending for precision");
EOS_ASSERT(neg || std::numeric_limits<decltype(consumed)>::max() - consumed >= units, rate_limiting_state_inconsistent, "Overflow in tracked usage when adding usage!");

auto value_ex_contrib = downgrade_cast<uint64_t>(integer_divide_ceil((uint128_t)units * Precision, (uint128_t)window_size));
EOS_ASSERT(neg || (std::numeric_limits<decltype(value_ex)>::max() - value_ex >= value_ex_contrib), rate_limiting_state_inconsistent, "Overflow in accumulated value when adding usage!");
Expand Down Expand Up @@ -136,6 +136,7 @@ using namespace int_arithmetic;
std::vector<usage_accumulator> block_usage_accumulators;
std::vector<int64_t> pending_usage;
std::vector<uint64_t> virtual_limits;
uint64_t ram_size = config::default_ram_size;
uint64_t reserved_ram_size = config::default_reserved_ram_size;
void update_virtual_limit(const resource_limits_config_object& cfg, resource_id res);
void add_pending_delta(int64_t delta, const resource_limits_config_object& config, resource_id res);
Expand Down Expand Up @@ -164,4 +165,4 @@ FC_REFLECT(eosio::chain::resource_limits::resource_usage_object, (id)(owner)(acc

FC_REFLECT(eosio::chain::resource_limits::resource_limits_config_object, (id)(limit_parameters)(account_usage_average_windows))

FC_REFLECT(eosio::chain::resource_limits::resource_limits_state_object, (id)(block_usage_accumulators)(pending_usage)(virtual_limits)(reserved_ram_size))
FC_REFLECT(eosio::chain::resource_limits::resource_limits_state_object, (id)(block_usage_accumulators)(pending_usage)(virtual_limits)(ram_size)(reserved_ram_size))
1 change: 1 addition & 0 deletions programs/create-genesis/genesis_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ struct genesis_create::genesis_create_impl final {
if (updated_accs.count(n) == 0) {
db.emplace<resource_usage_object>(n, [&](auto& u) {
u.owner = n;
u.accumulators.resize(resource_limits::resources_num);
});
}
}
Expand Down