Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions contracts/sysio.bios/sysio.bios.abi
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
{
"name": "max_kv_secondary_key_size",
"type": "uint32"
},
{
"name": "notify_cpu_stipend",
"type": "uint32"
}
]
},
Expand Down
Binary file modified contracts/sysio.bios/sysio.bios.wasm
Binary file not shown.
6 changes: 4 additions & 2 deletions contracts/sysio.system/src/sysio.system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace sysiosystem {
#ifndef SYSTEM_BLOCKCHAIN_PARAMETERS
set_blockchain_parameters( params );
#else
constexpr size_t param_count = 17;
constexpr size_t param_count = 18;
// an upper bound on the serialized size
char buf[1 + sizeof(params) + param_count];
datastream<char*> stream(buf, sizeof(buf));
Expand All @@ -77,7 +77,9 @@ namespace sysiosystem {
<< uint8_t(13) << params.max_action_return_value_size
<< uint8_t(14) << params.max_kv_key_size
<< uint8_t(15) << params.max_kv_value_size
<< uint8_t(16) << params.max_kv_secondary_key_size;
<< uint8_t(16) << params.max_kv_secondary_key_size

<< uint8_t(17) << params.notify_cpu_stipend;

set_parameters_packed(buf, stream.tellp());
#endif
Expand Down
4 changes: 4 additions & 0 deletions contracts/sysio.system/sysio.system.abi
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@
{
"name": "max_kv_secondary_key_size",
"type": "uint32"
},
{
"name": "notify_cpu_stipend",
"type": "uint32"
}
]
},
Expand Down
Binary file modified contracts/sysio.system/sysio.system.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions contracts/tests/sysio.system_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ class sysio_system_tester : public TESTER {
("max_kv_key_size", 256 + n)
("max_kv_value_size", 262144 + n)
("max_kv_secondary_key_size", 256 + n)
("notify_cpu_stipend", 100 + n)
("max_ram_size", (n % 10 + 1) * 1024 * 1024)
("ram_reserve_ratio", 100 + n);
}
Expand Down
3 changes: 2 additions & 1 deletion contracts/tests/sysio.system_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ fc::mutable_variant_object config_to_variant( const sysio::chain::chain_config&
( "max_action_return_value_size", config.max_action_return_value_size )
( "max_kv_key_size", config.max_kv_key_size )
( "max_kv_value_size", config.max_kv_value_size )
( "max_kv_secondary_key_size", config.max_kv_secondary_key_size );
( "max_kv_secondary_key_size", config.max_kv_secondary_key_size )
( "notify_cpu_stipend", config.notify_cpu_stipend );
}

BOOST_FIXTURE_TEST_CASE( setparams, sysio_system_tester ) try {
Expand Down
10 changes: 6 additions & 4 deletions libraries/chain/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

namespace sysio::chain {

account_name action::payer() const {
bool action::has_explicit_payer() const {
// sysio_payer_name must be position 0; enforced by validate_referenced_accounts
// and authorization_manager::check_authorization.
if (!authorization.empty() && authorization[0].permission == config::sysio_payer_name)
return authorization[0].actor;
return account;
return !authorization.empty() && authorization[0].permission == config::sysio_payer_name;
}

account_name action::payer() const {
return has_explicit_payer() ? authorization[0].actor : account;
}

account_name action::first_authorizer() const {
Expand Down
9 changes: 7 additions & 2 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ void apply_context::exec_one()
receiver_account = &db.get<account_object,by_name>( receiver );
receiver_account_metadata = db.find<account_metadata_object,by_name>( receiver );
privileged = receiver_account_metadata != nullptr && receiver_account_metadata->is_privileged();
const bool measured_frame = trx_context.begin_frame(
action_ordinal, config::is_system_account( receiver ) && privileged,
receiver_account_metadata != nullptr && receiver_account_metadata->code_hash != digest_type() );
auto native = control.find_apply_handler( receiver, act->account, act->name );
if( native ) {
if( trx_context.enforce_whiteblacklist && control.is_speculative_block() ) {
Expand Down Expand Up @@ -128,6 +131,8 @@ void apply_context::exec_one()
}
}
validate_account_ram_deltas();
if( measured_frame )
trx_context.end_frame( action_ordinal );
} FC_RETHROW_EXCEPTIONS( warn, "{} <= {}::{} pending console output: {}",
receiver, act->account, act->name, _pending_console_output )

Expand Down Expand Up @@ -215,7 +220,7 @@ void apply_context::validate_account_ram_deltas() {
auto& payer = itr->account;
auto& ram_delta = itr->delta;
if (payer != receiver && ram_delta > 0) {
if (receiver.prefix() == sysio::chain::config::system_account_name && is_privileged()) {
if (config::is_system_account(receiver) && is_privileged()) {
// sysio.* contracts allowed
} else if (payer == sysio::chain::config::system_account_name && is_privileged()) {
// explicit sysio payer allowed when privileged
Expand Down Expand Up @@ -534,7 +539,7 @@ action_name apply_context::get_sender() const {
}

bool apply_context::is_sys_vm_oc_whitelisted() const {
return receiver.prefix() == sysio::chain::config::system_account_name || // "sysio"_n
return config::is_system_account(receiver) ||
control.is_sys_vm_oc_whitelisted(receiver);
}

Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/chain_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace sysio { namespace chain {
"min transaction cpu usage cannot exceed max transaction cpu usage" );
SYS_ASSERT( max_transaction_cpu_usage < (max_block_cpu_usage - min_transaction_cpu_usage), action_validate_exception,
"max transaction cpu usage must be at less than the difference between the max block cpu usage and the min transaction cpu usage" );
SYS_ASSERT( notify_cpu_stipend <= max_transaction_cpu_usage, action_validate_exception,
"notify cpu stipend cannot exceed max transaction cpu usage" );

SYS_ASSERT( 1 <= max_authority_depth, action_validate_exception,
"max authority depth should be at least 1" );
Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3755,7 +3755,7 @@ subjective_billing& controller::get_mutable_subjective_billing() {
return my->subjective_bill;
}

std::tuple<int64_t, bool, bool> controller::get_cpu_limit(account_name a) const {
std::tuple<int64_t, bool, bool> controller::get_cpu_limit(account_name a, const std::optional<block_timestamp_type>& current_time) const {
static constexpr int64_t large_number_no_overflow = std::numeric_limits<int64_t>::max()/2;
// Calculate the new highest network usage and CPU time that the billed account can afford to be billed
const auto& rl = get_resource_limits_manager();
Expand All @@ -3771,7 +3771,7 @@ std::tuple<int64_t, bool, bool> controller::get_cpu_limit(account_name a) const
greylist_limit = specified_greylist_limit;
}
}
auto [cpu_limit, cpu_was_greylisted] = rl.get_account_cpu_limit(a, greylist_limit);
auto [cpu_limit, cpu_was_greylisted] = rl.get_account_cpu_limit(a, greylist_limit, current_time);
if( cpu_limit >= 0 ) {
account_cpu_limit = cpu_limit;
greylisted_cpu = cpu_was_greylisted;
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/sysio/chain/action.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ namespace sysio { namespace chain {
return value;
}

/// True when the first authorization names an explicit payer (permission sysio_payer_name).
bool has_explicit_payer() const;
// sysio_payer_name actor or contract
account_name payer() const;
// first authorization actor (which will be sysio_payer_name actor if exists) or empty() if no authorizer
Expand Down
8 changes: 6 additions & 2 deletions libraries/chain/include/sysio/chain/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ namespace sysio { namespace chain {
};
bool operator==(const transaction_receipt_header&) const = default;

cpu_usage_t cpu_usage_us; ///< billed CPU for nth input action
/// Billed CPU: one entry per input action, then one per frame whose billing switched to a contract reached
/// through a system contract, in execution order. A receiver entry covers its frame and the frames below it
/// billed to the same contract; the validator derives each entry's account by running the transaction. The
/// transaction's CPU is the sum of all entries.
cpu_usage_t cpu_usage_us;
};

struct transaction_receipt : public transaction_receipt_header {
Expand All @@ -21,7 +25,7 @@ namespace sysio { namespace chain {
packed_transaction trx;

// Receipt digest format: pack(cpu_usage_us: vec<varuint32>) + pack(trx.digest())
// cpu_usage_us is the per-input-action billed CPU vector, in action order.
// cpu_usage_us is the billed CPU vector: input actions in action order, then receiver entries.
// Differs from upstream EOSIO which packed status, cpu_usage_us (uint32), and
// net_usage_words ahead of the trx digest. Wire removed status and net_usage_words
// (deferred trxs are not supported) and changed cpu_usage_us to a per-action vector.
Expand Down
22 changes: 19 additions & 3 deletions libraries/chain/include/sysio/chain/chain_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct chain_config_v0 {
max_kv_key_size_id,
max_kv_value_size_id,
max_kv_secondary_key_size_id,
notify_cpu_stipend_id,
PARAMS_COUNT
};

Expand All @@ -58,6 +59,11 @@ struct chain_config_v0 {
uint32_t max_kv_value_size = config::default_max_kv_value_size; ///< maximum KV value size in bytes
uint32_t max_kv_secondary_key_size = config::default_max_kv_secondary_key_size; ///< maximum KV secondary key size in bytes

/// CPU (in microseconds) of a notified contract that the entry paying for the notifying frame covers: the contract
/// pays only past it, and 0 means no stipend. Applied where CPU is measured; validators bill a receipt's entries as
/// given.
uint32_t notify_cpu_stipend = config::default_notify_cpu_stipend;

void validate()const;

inline const chain_config_v0& v0() const {
Expand Down Expand Up @@ -86,7 +92,8 @@ struct chain_config_v0 {
lhs.max_action_return_value_size,
lhs.max_kv_key_size,
lhs.max_kv_value_size,
lhs.max_kv_secondary_key_size
lhs.max_kv_secondary_key_size,
lhs.notify_cpu_stipend
)
==
std::tie( rhs.max_block_net_usage,
Expand All @@ -105,7 +112,8 @@ struct chain_config_v0 {
rhs.max_action_return_value_size,
rhs.max_kv_key_size,
rhs.max_kv_value_size,
rhs.max_kv_secondary_key_size
rhs.max_kv_secondary_key_size,
rhs.notify_cpu_stipend
);
};

Expand All @@ -132,7 +140,8 @@ struct chain_config_v0 {
<< "Max Action Return Value Size: " << max_action_return_value_size << ", "
<< "Max KV Key Size: " << max_kv_key_size << ", "
<< "Max KV Value Size: " << max_kv_value_size << ", "
<< "Max KV Secondary Key Size: " << max_kv_secondary_key_size;
<< "Max KV Secondary Key Size: " << max_kv_secondary_key_size << ", "
<< "Notify CPU Stipend: " << notify_cpu_stipend;
}
};

Expand Down Expand Up @@ -163,6 +172,7 @@ FC_REFLECT(sysio::chain::chain_config_v0,

(max_action_return_value_size)
(max_kv_key_size)(max_kv_value_size)(max_kv_secondary_key_size)
(notify_cpu_stipend)
)

namespace fc {
Expand Down Expand Up @@ -234,6 +244,9 @@ inline DataStream &operator<<(DataStream &s, const sysio::chain::data_entry<sysi
case chain_config_v0::max_kv_secondary_key_size_id:
fc::raw::pack(s, entry.config.max_kv_secondary_key_size);
break;
case chain_config_v0::notify_cpu_stipend_id:
fc::raw::pack(s, entry.config.notify_cpu_stipend);
break;
default:
FC_THROW_EXCEPTION(config_parse_error, "DataStream& operator<<: no such id: {}", entry.id);
}
Expand Down Expand Up @@ -305,6 +318,9 @@ inline DataStream &operator>>(DataStream &s, sysio::chain::data_entry<sysio::cha
case chain_config_v0::max_kv_secondary_key_size_id:
fc::raw::unpack(s, entry.config.max_kv_secondary_key_size);
break;
case chain_config_v0::notify_cpu_stipend_id:
fc::raw::unpack(s, entry.config.notify_cpu_stipend);
break;
default:
FC_THROW_EXCEPTION(sysio::chain::config_parse_error, "DataStream& operator<<: no such id: {}", entry.id);
}
Expand Down
6 changes: 6 additions & 0 deletions libraries/chain/include/sysio/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ namespace sysio::chain::config {
static constexpr auto producers_account_name { "sysio.prods"_n };
static constexpr auto roa_account_name { "sysio.roa"_n };

/// True for sysio and every sysio.* account. Callers that grant a system contract more also require it to be
/// privileged.
constexpr bool is_system_account( name account ) { return account.prefix() == system_account_name; }

// Active permission of producers account requires greater than 2/3 of the producers to authorize
static constexpr auto majority_producers_permission_name { "prod.major"_n }; // greater than 1/2 of producers needed to authorize
static constexpr auto minority_producers_permission_name { "prod.minor"_n }; // greater than 1/3 of producers needed to authorize0
Expand Down Expand Up @@ -65,6 +69,8 @@ namespace sysio::chain::config {
static constexpr uint32_t default_min_transaction_cpu_usage = 100; /// min trx cpu usage in microseconds (10000 TPS equiv)
static constexpr uint32_t default_subjective_cpu_leeway_us = 31000; /// default subjective cpu leeway in microseconds
static constexpr uint32_t default_subjective_cpu_us = 300000; /// default subjective cpu given to each account
/// Genesis value of chain_config::notify_cpu_stipend, in microseconds
static constexpr uint32_t default_notify_cpu_stipend = 100;

static constexpr uint32_t default_max_trx_lifetime = 60*60; // 1 hour
static constexpr uint32_t default_max_trx_delay = 45*24*3600; // 45 days
Expand Down
5 changes: 3 additions & 2 deletions libraries/chain/include/sysio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,9 @@ namespace sysio::chain {
const subjective_billing& get_subjective_billing()const;
subjective_billing& get_mutable_subjective_billing();

// limit,greylisted,unlimited
std::tuple<int64_t, bool, bool> get_cpu_limit(account_name a) const;
/// CPU limit of `a` as (limit_us, greylisted, unlimited). `current_time` decays the account's usage to that
/// time first, for an account whose usage window was not updated in this block.
std::tuple<int64_t, bool, bool> get_cpu_limit(account_name a, const std::optional<block_timestamp_type>& current_time = {}) const;

const flat_set<account_name>& get_actor_whitelist() const;
const flat_set<account_name>& get_actor_blacklist() const;
Expand Down
4 changes: 3 additions & 1 deletion libraries/chain/include/sysio/chain/genesis_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ struct genesis_state {
.max_action_return_value_size = config::default_max_action_return_value_size, ///< size limit for action return value
.max_kv_key_size = config::default_max_kv_key_size, ///< maximum KV primary key size in bytes
.max_kv_value_size = config::default_max_kv_value_size, ///< maximum KV value size in bytes
.max_kv_secondary_key_size = config::default_max_kv_secondary_key_size ///< maximum KV secondary key size in bytes
.max_kv_secondary_key_size = config::default_max_kv_secondary_key_size, ///< maximum KV secondary key size in bytes

.notify_cpu_stipend = config::default_notify_cpu_stipend
};

static constexpr wasm_config default_initial_wasm_configuration {
Expand Down
5 changes: 4 additions & 1 deletion libraries/chain/include/sysio/chain/resource_limits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ namespace sysio { namespace chain {
uint64_t get_block_cpu_limit() const;
uint64_t get_block_net_limit() const;

std::pair<int64_t, bool> get_account_cpu_limit( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier ) const;
/// Available CPU for `name`. With `current_time`, usage decays to that time first, for an account whose window
/// update_account_usage has not brought up to date in this block.
std::pair<int64_t, bool> get_account_cpu_limit( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier,
const std::optional<block_timestamp_type>& current_time = {} ) const;
std::pair<int64_t, bool> get_account_net_limit( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier ) const;

std::pair<account_resource_limit, bool>
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/sysio/chain/trace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace sysio::chain {
action_name receiver;
action act;
fc::microseconds elapsed;
std::optional<fc::unsigned_int> cpu_usage_us; // only populated for input action
std::optional<fc::unsigned_int> cpu_usage_us; // populated for an input action and for a frame whose billing switched to its receiver
std::optional<fc::unsigned_int> net_usage; // only populated for input action
string console;
transaction_id_type trx_id; ///< the transaction that generated this action
Expand Down
Loading
Loading