Skip to content

Commit

Permalink
Merge pull request #1013 from AntelopeIO/GH-981-oc-whitelist
Browse files Browse the repository at this point in the history
eos-vm-oc-whitelist option
  • Loading branch information
heifner authored Nov 8, 2024
2 parents 854c770 + 1fdd7ad commit 0ee5778
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 55 deletions.
13 changes: 7 additions & 6 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,16 +1091,17 @@ action_name apply_context::get_sender() const {
}

bool apply_context::is_eos_vm_oc_whitelisted() const {
return receiver.prefix() == config::system_account_name; // "eosio"_n
return receiver.prefix() == config::system_account_name || // "eosio"_n
control.is_eos_vm_oc_whitelisted(receiver);
}

// Context | OC?
//-------------------------------------------------------------------------------
// Building block | baseline, OC for eosio.*
// Applying block | OC unless a producer, OC for eosio.* including producers
// Speculative API trx | baseline, OC for eosio.*
// Speculative P2P trx | baseline, OC for eosio.*
// Compute trx | baseline, OC for eosio.*
// Building block | baseline, OC for whitelisted
// Applying block | OC unless a producer, OC for whitelisted including producers
// Speculative API trx | baseline, OC for whitelisted
// Speculative P2P trx | baseline, OC for whitelisted
// Compute trx | baseline, OC for whitelisted
// Read only trx | OC
bool apply_context::should_use_eos_vm_oc()const {
return is_eos_vm_oc_whitelisted() // all whitelisted accounts use OC always
Expand Down
4 changes: 4 additions & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5743,6 +5743,10 @@ bool controller::is_profiling(account_name account) const {
return my->conf.profile_accounts.find(account) != my->conf.profile_accounts.end();
}

bool controller::is_eos_vm_oc_whitelisted(const account_name& n) const {
return my->conf.eos_vm_oc_whitelist_suffixes.count(n.suffix()) > 0;
}

chain_id_type controller::get_chain_id()const {
return my->chain_id;
}
Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ namespace eosio::chain {
wasm_interface::vm_type wasm_runtime = chain::config::default_wasm_runtime;
eosvmoc::config eosvmoc_config;
wasm_interface::vm_oc_enable eosvmoc_tierup = wasm_interface::vm_oc_enable::oc_auto;
flat_set<account_name> eos_vm_oc_whitelist_suffixes;

db_read_mode read_mode = db_read_mode::HEAD;
validation_mode block_validation_mode = validation_mode::FULL;
Expand Down Expand Up @@ -420,6 +421,8 @@ namespace eosio::chain {

bool is_profiling(account_name name) const;

bool is_eos_vm_oc_whitelisted(const account_name& n) const;

chain_id_type get_chain_id()const;

// thread safe
Expand Down
38 changes: 38 additions & 0 deletions libraries/chain/include/eosio/chain/name.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,44 @@ namespace eosio::chain {

return name{ result };
}

/**
* Returns the suffix.
* for example:
* "eosio.any" -> "any"
* "eosio" -> "eosio"
*/
constexpr name suffix() const {
uint32_t remaining_bits_after_last_actual_dot = 0;
uint32_t tmp = 0;
for (int32_t remaining_bits = 59; remaining_bits >= 4; remaining_bits -= 5) { // Note: remaining_bits must remain signed integer
// Get characters one-by-one in name in order from left to right (not including the 13th character)
auto c = (value >> remaining_bits) & 0x1Full;
if (!c) { // if this character is a dot
tmp = static_cast<uint32_t>(remaining_bits);
} else { // if this character is not a dot
remaining_bits_after_last_actual_dot = tmp;
}
}

uint64_t thirteenth_character = value & 0x0Full;
if (thirteenth_character) { // if 13th character is not a dot
remaining_bits_after_last_actual_dot = tmp;
}

if (remaining_bits_after_last_actual_dot == 0) // there is no actual dot in the %name other than potentially leading dots
return name{ value };

// At this point remaining_bits_after_last_actual_dot has to be within the range of 4 to 59 (and restricted to
// increments of 5).

// Mask for remaining bits corresponding to characters after last actual dot, except for 4 least significant bits
// (corresponds to 13th character).
uint64_t mask = (1ull << remaining_bits_after_last_actual_dot) - 16;
uint32_t shift = 64 - remaining_bits_after_last_actual_dot;

return name{ ((value & mask) << shift) + (thirteenth_character << (shift - 1)) };
}
};

// Each char of the string is encoded into 5-bit chunk and left-shifted
Expand Down
19 changes: 19 additions & 0 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@
const std::string deep_mind_logger_name("deep-mind");
eosio::chain::deep_mind_handler _deep_mind_log;

namespace std {
// declare operator<< for boost program options of vector<string>
std::ostream& operator<<(std::ostream& osm, const std::vector<std::string>& v) {
auto size = v.size();
osm << "{";
for (size_t i = 0; i < size; ++i) {
osm << v[i];
if (i < size - 1) {
osm << ", ";
}
}
osm << "}";
return osm;
}
}

namespace eosio {

//declare operator<< and validate function for read_mode in the same namespace as read_mode itself
Expand Down Expand Up @@ -356,6 +372,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
"'auto' - EOS VM OC tier-up is enabled for eosio.* accounts, read-only trxs, and except on producers applying blocks.\n"
"'all' - EOS VM OC tier-up is enabled for all contract execution.\n"
"'none' - EOS VM OC tier-up is completely disabled.\n")
("eos-vm-oc-whitelist", bpo::value<vector<string>>()->composing()->default_value(std::vector<string>{{"xsat"}}),
"EOS VM OC tier-up whitelist account suffixes for tier-up runtime 'auto'.")
#endif
("enable-account-queries", bpo::value<bool>()->default_value(false), "enable queries to find accounts by various metadata.")
("transaction-retry-max-storage-size-gb", bpo::value<uint64_t>(),
Expand Down Expand Up @@ -520,6 +538,7 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) {
LOAD_VALUE_SET( options, "actor-blacklist", chain_config->actor_blacklist );
LOAD_VALUE_SET( options, "contract-whitelist", chain_config->contract_whitelist );
LOAD_VALUE_SET( options, "contract-blacklist", chain_config->contract_blacklist );
LOAD_VALUE_SET( options, "eos-vm-oc-whitelist", chain_config->eos_vm_oc_whitelist_suffixes);

LOAD_VALUE_SET( options, "trusted-producer", chain_config->trusted_producers );

Expand Down
21 changes: 20 additions & 1 deletion plugins/chain_plugin/test/plugin_config_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,23 @@ BOOST_AUTO_TEST_CASE(chain_plugin_default_tests) {
auto* config = std::get_if<eosio::chain::partitioned_blocklog_config>(&plugin.chain_config().blog);
BOOST_REQUIRE(config);
BOOST_CHECK_EQUAL(config->max_retained_files, UINT32_MAX);
}

// test default eos-vm-oc-whitelist
BOOST_CHECK(plugin.chain().is_eos_vm_oc_whitelisted(eosio::chain::name{"xsat"}));
}

BOOST_AUTO_TEST_CASE(chain_plugin_eos_vm_oc_whitelist) {
fc::temp_directory tmp;
appbase::scoped_app app;

auto tmp_path = tmp.path().string();
std::array args = {
"test_chain_plugin", "--eos-vm-oc-whitelist", "hello", "--data-dir", tmp_path.c_str(),
};

BOOST_CHECK(app->initialize<eosio::chain_plugin>(args.size(), const_cast<char**>(args.data())));
auto& plugin = app->get_plugin<eosio::chain_plugin>();
BOOST_CHECK(plugin.chain().is_eos_vm_oc_whitelisted(eosio::chain::name{"hello"}));
BOOST_CHECK(plugin.chain().is_eos_vm_oc_whitelisted(eosio::chain::name{"xs.hello"}));
BOOST_CHECK(!plugin.chain().is_eos_vm_oc_whitelisted(eosio::chain::name{"xsat"}));
}
88 changes: 40 additions & 48 deletions unittests/misc_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,42 +74,10 @@ FC_REFLECT( base_reflect, (bv) )
FC_REFLECT_DERIVED( derived_reflect, (base_reflect), (dv) )
FC_REFLECT_DERIVED( final_reflect, (derived_reflect), (fv) )

namespace eosio
{
namespace eosio {
using namespace chain;
using namespace std;

static constexpr uint64_t name_suffix( name nv ) {
uint64_t n = nv.to_uint64_t();
uint32_t remaining_bits_after_last_actual_dot = 0;
uint32_t tmp = 0;
for( int32_t remaining_bits = 59; remaining_bits >= 4; remaining_bits -= 5 ) { // Note: remaining_bits must remain signed integer
// Get characters one-by-one in name in order from left to right (not including the 13th character)
auto c = (n >> remaining_bits) & 0x1Full;
if( !c ) { // if this character is a dot
tmp = static_cast<uint32_t>(remaining_bits);
} else { // if this character is not a dot
remaining_bits_after_last_actual_dot = tmp;
}
}

uint64_t thirteenth_character = n & 0x0Full;
if( thirteenth_character ) { // if 13th character is not a dot
remaining_bits_after_last_actual_dot = tmp;
}

if( remaining_bits_after_last_actual_dot == 0 ) // there is no actual dot in the name other than potentially leading dots
return n;

// At this point remaining_bits_after_last_actual_dot has to be within the range of 4 to 59 (and restricted to increments of 5).

// Mask for remaining bits corresponding to characters after last actual dot, except for 4 least significant bits (corresponds to 13th character).
uint64_t mask = (1ull << remaining_bits_after_last_actual_dot) - 16;
uint32_t shift = 64 - remaining_bits_after_last_actual_dot;

return ( ((n & mask) << shift) + (thirteenth_character << (shift-1)) );
}

BOOST_AUTO_TEST_SUITE(misc_tests)

BOOST_AUTO_TEST_CASE(reverse_endian_tests)
Expand All @@ -122,21 +90,45 @@ BOOST_AUTO_TEST_CASE(reverse_endian_tests)

BOOST_AUTO_TEST_CASE(name_suffix_tests)
{
BOOST_CHECK_EQUAL( name{name_suffix(name(0))}, name{0} );
BOOST_CHECK_EQUAL( name{name_suffix("abcdehijklmn"_n)}, name{"abcdehijklmn"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("abcdehijklmn1"_n)}, name{"abcdehijklmn1"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("abc.def"_n)}, name{"def"_n} );
BOOST_CHECK_EQUAL( name{name_suffix(".abc.def"_n)}, name{"def"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("..abc.def"_n)}, name{"def"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("abc..def"_n)}, name{"def"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("abc.def.ghi"_n)}, name{"ghi"_n} );
BOOST_CHECK_EQUAL( name{name_suffix(".abcdefghij"_n)}, name{"abcdefghij"_n} );
BOOST_CHECK_EQUAL( name{name_suffix(".abcdefghij.1"_n)}, name{"1"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("a.bcdefghij"_n)}, name{"bcdefghij"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("a.bcdefghij.1"_n)}, name{"1"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("......a.b.c"_n)}, name{"c"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("abcdefhi.123"_n)}, name{"123"_n} );
BOOST_CHECK_EQUAL( name{name_suffix("abcdefhij.123"_n)}, name{"123"_n} );
BOOST_CHECK_EQUAL( name(0).suffix(), name{0} );
BOOST_CHECK_EQUAL( name{"eosio"_n}.suffix(), name{"eosio"_n} );
BOOST_CHECK_EQUAL( name{"eosio.any"_n}.suffix(), name{"any"_n} );
BOOST_CHECK_EQUAL( name{"abcdehijklmn"_n}.suffix(), name{"abcdehijklmn"_n} );
BOOST_CHECK_EQUAL( name{"abcdehijklmn1"_n}.suffix(), name{"abcdehijklmn1"_n} );
BOOST_CHECK_EQUAL( name{"abc.def"_n}.suffix(), name{"def"_n} );
BOOST_CHECK_EQUAL( name{".abc.def"_n}.suffix(), name{"def"_n} );
BOOST_CHECK_EQUAL( name{"..abc.def"_n}.suffix(), name{"def"_n} );
BOOST_CHECK_EQUAL( name{"abc..def"_n}.suffix(), name{"def"_n} );
BOOST_CHECK_EQUAL( name{"abc.def.ghi"_n}.suffix(), name{"ghi"_n} );
BOOST_CHECK_EQUAL( name{".abcdefghij"_n}.suffix(), name{"abcdefghij"_n} );
BOOST_CHECK_EQUAL( name{".abcdefghij.1"_n}.suffix(), name{"1"_n} );
BOOST_CHECK_EQUAL( name{"a.bcdefghij"_n}.suffix(), name{"bcdefghij"_n} );
BOOST_CHECK_EQUAL( name{"a.bcdefghij.1"_n}.suffix(), name{"1"_n} );
BOOST_CHECK_EQUAL( name{"......a.b.c"_n}.suffix(), name{"c"_n} );
BOOST_CHECK_EQUAL( name{"abcdefhi.123"_n}.suffix(), name{"123"_n} );
BOOST_CHECK_EQUAL( name{"abcdefhij.123"_n}.suffix(), name{"123"_n} );
}

BOOST_AUTO_TEST_CASE(name_suffix_additional_tests) {
// ----------------------------
// constexpr name suffix()const
BOOST_CHECK_EQUAL( name{".eosioaccounj"}.suffix(), name{"eosioaccounj"} );
BOOST_CHECK_EQUAL( name{"e.osioaccounj"}.suffix(), name{"osioaccounj"} );
BOOST_CHECK_EQUAL( name{"eo.sioaccounj"}.suffix(), name{"sioaccounj"} );
BOOST_CHECK_EQUAL( name{"eos.ioaccounj"}.suffix(), name{"ioaccounj"} );
BOOST_CHECK_EQUAL( name{"eosi.oaccounj"}.suffix(), name{"oaccounj"} );
BOOST_CHECK_EQUAL( name{"eosio.accounj"}.suffix(), name{"accounj"} );
BOOST_CHECK_EQUAL( name{"eosioa.ccounj"}.suffix(), name{"ccounj"} );
BOOST_CHECK_EQUAL( name{"eosioac.counj"}.suffix(), name{"counj"} );
BOOST_CHECK_EQUAL( name{"eosioacc.ounj"}.suffix(), name{"ounj"} );
BOOST_CHECK_EQUAL( name{"eosioacco.unj"}.suffix(), name{"unj"} );
BOOST_CHECK_EQUAL( name{"eosioaccou.nj"}.suffix(), name{"nj"} );
BOOST_CHECK_EQUAL( name{"eosioaccoun.j"}.suffix(), name{"j"} );
BOOST_CHECK_EQUAL( name{"eosioaccounja"}.suffix(), name{"eosioaccounja"} );
BOOST_CHECK_EQUAL( name{"eosioaccounj"}.suffix(), name{"eosioaccounj"} );

BOOST_CHECK_EQUAL( name{"e.o.s.i.o.a.c"}.suffix(), name{"c"} );
BOOST_CHECK_EQUAL( name{"eos.ioa.cco"}.suffix(), name{"cco"} );
}

BOOST_AUTO_TEST_CASE(name_prefix_tests)
Expand Down

0 comments on commit 0ee5778

Please sign in to comment.