Skip to content

Commit

Permalink
Implement ram owner. #473
Browse files Browse the repository at this point in the history
  • Loading branch information
afalaleev committed Apr 17, 2019
1 parent 9da5be5 commit 575dfcd
Show file tree
Hide file tree
Showing 16 changed files with 133 additions and 59 deletions.
21 changes: 8 additions & 13 deletions libraries/chain/apply_context.cpp
Expand Up @@ -517,17 +517,22 @@ bytes apply_context::get_packed_transaction() {
return r;
}

void apply_context::update_db_usage( const account_name& payer, int64_t delta ) {
void apply_context::add_ram_usage( const account_name& payer, const int64_t delta ) {
if( delta > 0 ) {
if( !(privileged || payer == account_name(receiver)) ) {
EOS_ASSERT( control.is_ram_billing_in_notify_allowed() || (receiver == act.account),
subjective_block_production_exception, "Cannot charge RAM to other accounts during notify." );
require_authorization( payer );
}
}
add_ram_usage(payer, delta);
}

trx_context.add_ram_usage( payer, delta );

auto p = _account_ram_deltas.emplace( payer, delta );
if( !p.second ) {
p.first->delta += delta;
}
}

int apply_context::get_action( uint32_t type, uint32_t index, char* buffer, size_t buffer_size )const
{
Expand Down Expand Up @@ -789,14 +794,4 @@ uint64_t apply_context::next_auth_sequence( account_name actor ) {
return rs.auth_sequence;
}

void apply_context::add_ram_usage( account_name account, int64_t ram_delta ) {
trx_context.add_ram_usage( account, ram_delta );

auto p = _account_ram_deltas.emplace( account, ram_delta );
if( !p.second ) {
p.first->delta += ram_delta;
}
}


} } /// eosio::chain
30 changes: 23 additions & 7 deletions libraries/chain/chaindb/controller.cpp
Expand Up @@ -12,11 +12,11 @@

#include <eosio/chain/name.hpp>
#include <eosio/chain/symbol.hpp>

#include <boost/algorithm/string.hpp>

#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/transaction_context.hpp>

#include <boost/algorithm/string.hpp>

namespace cyberway { namespace chaindb {

Expand Down Expand Up @@ -110,15 +110,24 @@ namespace cyberway { namespace chaindb {

} } // namespace _detail

//------------------------------------

void ram_payer_info::add_usage(const account_name new_payer, const int64_t delta) const {
if (delta < 0 && rl) {
rl->add_pending_ram_usage( new_payer, delta );
if (BOOST_UNLIKELY(new_payer.empty() || !delta)) {
return;
}
if (!ctx || new_payer.empty() || !delta) return;

const_cast<apply_context&>(*ctx).update_db_usage(new_payer, delta);
if (BOOST_LIKELY(!!apply_ctx)) {
apply_ctx->add_ram_usage(new_payer, delta);
} else if (!!resource_mng) {
resource_mng->add_pending_ram_usage(new_payer, delta);
} else if (!!transaction_ctx) {
transaction_ctx->add_ram_usage(new_payer, delta);
}
}

//------------------------------------

struct chaindb_controller::controller_impl_ final {
journal journal_;
std::unique_ptr<driver_interface> driver_ptr_;
Expand Down Expand Up @@ -570,6 +579,7 @@ namespace cyberway { namespace chaindb {
obj.service.revision = undo_.revision();
obj.service.size = calc_ram_usage(ram, table, obj);
obj.service.payer = ram.payer;
obj.service.owner = ram.owner;

// charge the payer
auto delta = static_cast<int64_t>(obj.service.size);
Expand All @@ -591,6 +601,12 @@ namespace cyberway { namespace chaindb {
obj.service.payer = ram.payer;
}

if (ram.owner.empty()) {
obj.service.owner = orig_obj.service.owner;
} else {
obj.service.owner = ram.owner;
}

auto delta = static_cast<int64_t>(obj.service.size) - static_cast<int64_t>(orig_obj.service.size);

if (obj.service.payer != orig_obj.service.payer) {
Expand Down
18 changes: 16 additions & 2 deletions libraries/chain/chaindb/mongo_driver_utils.cpp
Expand Up @@ -222,8 +222,9 @@ namespace cyberway { namespace chaindb {
}

void build_service_state(service_state& state, const document_view& src) {
bool has_size = false;
bool has_size = false;
bool has_payer = false;
bool has_owner = false;
bool has_scope = false;
for (auto& itm: src) try {
auto key = itm.key().to_string();
Expand Down Expand Up @@ -260,6 +261,12 @@ namespace cyberway { namespace chaindb {
}
break;
}
case 'o': {
validate_field_type(type::k_utf8 == key_type, src, itm);
state.owner = account_name(itm.get_utf8().value.to_string());
has_owner = true;
break;
}
case 'p': {
if (key == names::pk_field) {
validate_field_type(type::k_decimal128 == key_type, src, itm);
Expand Down Expand Up @@ -292,6 +299,9 @@ namespace cyberway { namespace chaindb {
} else if (key == names::undo_payer_field) {
validate_field_type(type::k_utf8 == key_type, src, itm);
state.undo_payer = account_name(itm.get_utf8().value.to_string());
} else if (key == names::undo_owner_field) {
validate_field_type(type::k_utf8 == key_type, src, itm);
state.undo_owner = account_name(itm.get_utf8().value.to_string());
} else if (key == names::undo_size_field) {
validate_field_type(type::k_int32 == key_type, src, itm);
state.undo_size = itm.get_int32().value;
Expand All @@ -309,9 +319,10 @@ namespace cyberway { namespace chaindb {
} catch(...) {
validate_field_type(false, src, itm);
}
validate_exist_field(has_size, names::size_field, src);
validate_exist_field(has_size, names::size_field, src);
validate_exist_field(has_scope, names::scope_field, src);
validate_exist_field(has_payer, names::payer_field, src);
validate_exist_field(has_owner, names::owner_field, src);
}

void build_variant(service_state* state, mutable_variant_object& dst, string key, const element& src) {
Expand Down Expand Up @@ -545,6 +556,7 @@ namespace cyberway { namespace chaindb {
serv_doc.append(kvp(names::scope_field, get_scope_name(table)));
serv_doc.append(kvp(names::revision_field, obj.service.revision));
serv_doc.append(kvp(names::payer_field, get_payer_name(obj.service.payer)));
serv_doc.append(kvp(names::owner_field, get_owner_name(obj.service.owner)));
serv_doc.append(kvp(names::size_field, static_cast<int32_t>(obj.service.size)));
}));
return doc;
Expand All @@ -555,13 +567,15 @@ namespace cyberway { namespace chaindb {
serv_doc.append(kvp(names::undo_pk_field, to_decimal128(obj.service.undo_pk)));
serv_doc.append(kvp(names::undo_rec_field, fc::reflector<undo_record>::to_string(obj.service.undo_rec)));
serv_doc.append(kvp(names::undo_payer_field, get_payer_name(obj.service.undo_payer)));
serv_doc.append(kvp(names::undo_owner_field, get_payer_name(obj.service.undo_owner)));
serv_doc.append(kvp(names::undo_size_field, static_cast<int32_t>(obj.service.undo_size)));
serv_doc.append(kvp(names::code_field, get_code_name(table)));
serv_doc.append(kvp(names::table_field, get_table_name(table)));
serv_doc.append(kvp(names::scope_field, get_scope_name(table)));
serv_doc.append(kvp(names::pk_field, to_decimal128(obj.service.pk)));
serv_doc.append(kvp(names::revision_field, obj.service.revision));
serv_doc.append(kvp(names::payer_field, get_payer_name(obj.service.payer)));
serv_doc.append(kvp(names::owner_field, get_owner_name(obj.service.owner)));
serv_doc.append(kvp(names::size_field, static_cast<int32_t>(obj.service.size)));
}));
return doc;
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/chaindb/names.cpp
Expand Up @@ -76,11 +76,13 @@ namespace cyberway { namespace chaindb {
const string names::next_pk_field = "npk";
const string names::undo_pk_field = "upk";
const string names::undo_payer_field = "upr";
const string names::undo_owner_field = "uow";
const string names::undo_size_field = "usz";
const string names::undo_rec_field = "rec";
const string names::revision_field = "rev";

const string names::payer_field = "payer";
const string names::owner_field = "owner";
const string names::size_field = "size";

const string names::scope_path = string(names::service_field).append(".").append(names::scope_field);
Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/chaindb/undo_state.cpp
Expand Up @@ -533,6 +533,7 @@ namespace cyberway { namespace chaindb {
void restore_undo_state(object_value& obj) {
obj.service.revision = obj.service.undo_revision;
obj.service.payer = obj.service.undo_payer;
obj.service.owner = obj.service.undo_owner;
obj.service.size = obj.service.undo_size;
}

Expand Down Expand Up @@ -866,6 +867,7 @@ namespace cyberway { namespace chaindb {

void copy_undo_object(object_value& dst, const object_value& src) {
dst.service.payer = src.service.payer;
dst.service.owner = src.service.owner;
dst.service.size = src.service.size;
}

Expand All @@ -877,6 +879,7 @@ namespace cyberway { namespace chaindb {
void init_undo_object(object_value& dst, undo_record rec) {
dst.service.undo_revision = dst.service.revision;
dst.service.undo_payer = dst.service.payer;
dst.service.undo_owner = dst.service.owner;
dst.service.undo_size = dst.service.size;

dst.service.revision = revision_;
Expand Down
4 changes: 1 addition & 3 deletions libraries/chain/controller.cpp
Expand Up @@ -773,9 +773,7 @@ struct controller_impl {
// );
// No need to verify_account_ram_usage since we are only reducing memory

auto payer = gto.payer;
auto delta = chaindb.erase( gto );
resource_limits.add_pending_ram_usage(payer, delta);
chaindb.erase( gto, {resource_limits} );
}

bool failure_is_subjective( const fc::exception& e ) const {
Expand Down
8 changes: 5 additions & 3 deletions libraries/chain/genesis/genesis_import.cpp
Expand Up @@ -18,12 +18,14 @@ const fc::microseconds abi_serializer_max_time = fc::seconds(10);
struct genesis_import::impl final {
bfs::path _state_file;

resource_manager& resource_mng;
chaindb_controller& db;
int db_updates;

impl(const bfs::path& genesis_file, controller& ctrl)
: _state_file(genesis_file)
, db(const_cast<chaindb_controller&>(ctrl.chaindb())) {
, resource_mng(ctrl.get_mutable_resource_limits_manager())
, db(ctrl.chaindb()) {
}

void apply_db_changes(bool force = false) {
Expand Down Expand Up @@ -54,7 +56,7 @@ struct genesis_import::impl final {
int i = 0;
if (t.code == config::system_account_name) {
while (i++ < t.count) {
sys_table_row r;
sys_table_row r(resource_mng);
fc::raw::unpack(in, r);
EOS_ASSERT(r.data.size() >= 8, extract_genesis_exception, "System table row is too small");
primary_key_t pk = ((primary_key_t*)r.data.data())[0]; // all system tables have pk in the 1st field
Expand All @@ -80,7 +82,7 @@ struct genesis_import::impl final {
}
} else {
while (i++ < t.count) {
table_row r;
table_row r(resource_mng);
fc::raw::unpack(in, r);
db.insert(r.request(t.code, t.name), r.payer(), r.pk, r.data.data(), r.data.size());
apply_db_changes();
Expand Down
6 changes: 6 additions & 0 deletions libraries/chain/include/cyberway/chaindb/names.hpp
Expand Up @@ -22,10 +22,12 @@ namespace cyberway { namespace chaindb {
static const string undo_pk_field;
static const string undo_rec_field;
static const string undo_payer_field;
static const string undo_owner_field;
static const string undo_size_field;
static const string revision_field;

static const string payer_field;
static const string owner_field;
static const string size_field;

static const string scope_path;
Expand Down Expand Up @@ -87,6 +89,10 @@ namespace cyberway { namespace chaindb {
return payer.to_string();
}

inline string get_owner_name(const account_name& owner) {
return owner.to_string();
}

///----

inline string get_table_name(const table_name& table) {
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/cyberway/chaindb/object_value.hpp
Expand Up @@ -15,6 +15,7 @@ namespace cyberway { namespace chaindb {
struct service_state final {
primary_key_t pk = unset_primary_key;
account_name payer;
account_name owner;
size_t size = 0;

account_name code;
Expand All @@ -28,6 +29,7 @@ namespace cyberway { namespace chaindb {

revision_t undo_revision = impossible_revision;
account_name undo_payer;
account_name undo_owner;
size_t undo_size = 0;

service_state(const table_info& table, primary_key_t pk)
Expand Down
42 changes: 30 additions & 12 deletions libraries/chain/include/cyberway/chaindb/ram_payer_info.hpp
Expand Up @@ -3,34 +3,52 @@
#include <cyberway/chaindb/common.hpp>

namespace eosio { namespace chain {
class apply_context;
class apply_context;
class transaction_context;
namespace resource_limits {
class resource_limits_manager;
class resource_limits_manager;
}
} } // namespace eosio::chain

namespace cyberway { namespace chaindb {

using eosio::chain::apply_context;
using eosio::chain::resource_limits::resource_limits_manager;
using apply_context = eosio::chain::apply_context;
using resource_manager = eosio::chain::resource_limits::resource_limits_manager;
using transaction_context = eosio::chain::transaction_context;

struct ram_payer_info final {
apply_context* ctx = nullptr; // maybe unavailable - see eosio controller
account_name payer;
size_t precalc_size = 0;
resource_limits_manager* rl = nullptr;
apply_context* apply_ctx = nullptr;
resource_manager* resource_mng = nullptr;
transaction_context* transaction_ctx = nullptr;

const account_name owner;
const account_name payer;
const size_t precalc_size = 0;

ram_payer_info() = default;

ram_payer_info(apply_context& c, account_name p = account_name(), const size_t s = 0)
: ctx(&c), payer(std::move(p)), precalc_size(s) {
ram_payer_info(apply_context& c, account_name p = {}, account_name o = {}, const size_t s = 0)
: apply_ctx(&c), owner(select_owner(p, o)), payer(std::move(p)), precalc_size(s) {
}

ram_payer_info(resource_limits_manager& r, account_name p = account_name(), const size_t s = 0)
: ctx(nullptr), payer(std::move(p)), precalc_size(s), rl(&r) {
ram_payer_info(resource_manager& r, account_name p = {}, account_name o = {}, const size_t s = 0)
: resource_mng(&r), owner(select_owner(p, o)), payer(std::move(p)), precalc_size(s) {
}

ram_payer_info(transaction_context& t, account_name p = {}, account_name o = {}, const size_t s = 0)
: transaction_ctx(&t), owner(select_owner(p, o)), payer(std::move(p)), precalc_size(s) {
}

void add_usage(const account_name, const int64_t delta) const;

private:
static account_name select_owner(account_name p, account_name o) {
if (o.empty()) {
return p;
} else {
return o;
}
}
}; // struct ram_payer_info

} } // namespace cyberway::chaindb

0 comments on commit 575dfcd

Please sign in to comment.