Skip to content

Commit

Permalink
move create_slim_account to eosio contract
Browse files Browse the repository at this point in the history
  • Loading branch information
quocle108 committed Jul 9, 2024
1 parent 888cc2a commit 4a176cb
Show file tree
Hide file tree
Showing 23 changed files with 268 additions and 367 deletions.
9 changes: 1 addition & 8 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ struct controller_impl {
set_activation_handler<builtin_protocol_feature_t::crypto_primitives>();
set_activation_handler<builtin_protocol_feature_t::bls_primitives>();
set_activation_handler<builtin_protocol_feature_t::disable_deferred_trxs_stage_2>();
set_activation_handler<builtin_protocol_feature_t::slim_account>();

self.irreversible_block.connect([this](const block_signal_params& t) {
const auto& [ block, id] = t;
Expand All @@ -360,6 +359,7 @@ struct controller_impl {
&BOOST_PP_CAT(apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) )

SET_APP_HANDLER( eosio, eosio, newaccount );
SET_APP_HANDLER( eosio, eosio, newslimacc );
SET_APP_HANDLER( eosio, eosio, setcode );
SET_APP_HANDLER( eosio, eosio, setabi );
SET_APP_HANDLER( eosio, eosio, updateauth );
Expand Down Expand Up @@ -3935,13 +3935,6 @@ void controller_impl::on_activation<builtin_protocol_feature_t::disable_deferred
}
}

template<>
void controller_impl::on_activation<builtin_protocol_feature_t::slim_account>() {
db.modify( db.get<protocol_state_object>(), [&]( auto& ps ) {
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "create_slim_account" );
} );
}

/// End of protocol feature activation handlers

} } /// eosio::chain
55 changes: 55 additions & 0 deletions libraries/chain/eosio_contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,61 @@ void apply_eosio_newaccount(apply_context& context) {

} FC_CAPTURE_AND_RETHROW( (create) ) }

/**
* This method is called assuming precondition_system_newslimacc succeeds
*/
void apply_eosio_newslimacc(apply_context& context) {
EOS_ASSERT( !context.trx_context.is_read_only(), action_validate_exception, "newslimacc not allowed in read-only transaction" );
if(!context.control.is_builtin_activated( builtin_protocol_feature_t::slim_account )) {
EOS_THROW( protocol_feature_validation_exception,
"Unsupported protocol_feature_t: ${type}",
("type", static_cast<uint32_t>(builtin_protocol_feature_t::slim_account))
);
}
auto create = context.get_action().data_as<newslimacc>();
try {
context.require_authorization(create.creator);
auto& authorization = context.control.get_mutable_authorization_manager();
EOS_ASSERT( validate(create.active), action_validate_exception, "Invalid active authority");
auto& db = context.db;

auto name_str = name(create.name).to_string();
EOS_ASSERT( !create.name.empty(), action_validate_exception, "account name cannot be empty" );
EOS_ASSERT( name_str.size() <= 12, action_validate_exception, "account names can only be 12 chars long" );

// system account only can be created by newaccount
EOS_ASSERT( name_str.find( "eosio." ) != 0, action_validate_exception,
"only newaccount action can create account with name start with 'eosio.'" );

auto existing_account = db.find<account_object, by_name>(create.name);
EOS_ASSERT(existing_account == nullptr, account_name_exists_exception,
"Cannot create account named ${name}, as that name is already taken",
("name", create.name));

db.create<account_object>([&](auto& a) {
a.name = create.name;
a.creation_date = context.control.pending_block_time();
});

for (const auto& auth : { create.active }) {
validate_authority_precondition( context, auth );
}

const auto& active_permission = authorization.create_permission( create.name, config::active_name, 0,
std::move(create.active), context.trx_context.is_transient() );
int64_t ram_delta = config::overhead_per_account_ram_bytes;
ram_delta -= config::billable_size_v<account_metadata_object>;
ram_delta += config::billable_size_v<permission_object>;
ram_delta += active_permission.auth.get_billable_size();
context.control.get_mutable_resource_limits_manager().initialize_account(create.name, context.trx_context.is_transient());

if (auto dm_logger = context.control.get_deep_mind_logger(context.trx_context.is_transient())) {
dm_logger->on_ram_trace(RAM_EVENT_ID("${name}", ("name", create.name)), "account", "add", "newslimacc");
}

context.add_ram_usage(create.name, ram_delta);
} FC_CAPTURE_AND_RETHROW( (create) ) }

void apply_eosio_setcode(apply_context& context) {
EOS_ASSERT( !context.trx_context.is_read_only(), action_validate_exception, "setcode not allowed in read-only transaction" );
auto& db = context.db;
Expand Down
9 changes: 9 additions & 0 deletions libraries/chain/eosio_contract_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ abi_def eosio_contract_abi(const abi_def& eosio_system_abi)
}
});

eos_abi.structs.emplace_back( struct_def {
"newslimacc", "", {
{"creator", "account_name"},
{"name", "account_name"},
{"active", "authority"},
}
});

eos_abi.structs.emplace_back( struct_def {
"setcode", "", {
{"account", "account_name"},
Expand Down Expand Up @@ -215,6 +223,7 @@ abi_def eosio_contract_abi(const abi_def& eosio_system_abi)

// TODO add ricardian contracts
eos_abi.actions.push_back( action_def{name("newaccount"), "newaccount",""} );
eos_abi.actions.push_back( action_def{name("newslimacc"), "newslimacc",""} );
eos_abi.actions.push_back( action_def{name("setcode"), "setcode",""} );
eos_abi.actions.push_back( action_def{name("setabi"), "setabi",""} );
eos_abi.actions.push_back( action_def{name("updateauth"), "updateauth",""} );
Expand Down
15 changes: 15 additions & 0 deletions libraries/chain/include/eosio/chain/contract_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ struct newaccount {
}
};

struct newslimacc {
account_name creator;
account_name name;
authority active;

static account_name get_account() {
return config::system_account_name;
}

static action_name get_name() {
return "newslimacc"_n;
}
};

struct setcode {
account_name account;
uint8_t vmtype = 0;
Expand Down Expand Up @@ -155,6 +169,7 @@ struct onerror {
} } /// namespace eosio::chain

FC_REFLECT( eosio::chain::newaccount , (creator)(name)(owner)(active) )
FC_REFLECT( eosio::chain::newslimacc , (creator)(name)(active) )
FC_REFLECT( eosio::chain::setcode , (account)(vmtype)(vmversion)(code) )
FC_REFLECT( eosio::chain::setabi , (account)(abi) )
FC_REFLECT( eosio::chain::updateauth , (account)(permission)(parent)(auth) )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,7 @@ inline constexpr auto get_intrinsic_table() {
"env.bls_g2_map",
"env.bls_fp_mod",
"env.bls_fp_mul",
"env.bls_fp_exp",
"env.create_slim_account"
"env.bls_fp_exp"
);
}
inline constexpr std::size_t find_intrinsic_index(std::string_view hf) {
Expand Down
11 changes: 0 additions & 11 deletions libraries/chain/include/eosio/chain/webassembly/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,17 +249,6 @@ namespace webassembly {
*/
void set_privileged(account_name account, bool is_priv);

/**
* create a slim account.
*
* @ingroup privileged
*
* @param account - account creator.
* @param name - new slim account name.
* @param pubkey - publickey.
*/
void create_slim_account(account_name creator, account_name name, legacy_span<const char> packed_authority);

// softfloat api
float _eosio_f32_add(float, float) const;
float _eosio_f32_sub(float, float) const;
Expand Down
69 changes: 0 additions & 69 deletions libraries/chain/webassembly/privileged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <eosio/chain/transaction_context.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/authorization_manager.hpp>

#include <fc/io/datastream.hpp>

Expand Down Expand Up @@ -225,72 +224,4 @@ namespace eosio { namespace chain { namespace webassembly {
ma.set_privileged( is_priv );
});
}
void interface::create_slim_account(account_name creator, account_name name, legacy_span<const char> packed_authority){
EOS_ASSERT( !context.trx_context.is_read_only(), wasm_execution_error, "create_slim_account not allowed in read-only transaction" );
authority active_auth;
fc::datastream<const char*> pubds ( packed_authority.data(), packed_authority.size() );

fc::raw::unpack( pubds, active_auth );

auto& authorization = context.control.get_mutable_authorization_manager();

EOS_ASSERT( validate(active_auth), action_validate_exception, "Invalid active authority");

auto& db = context.db;

auto name_str = name.to_string();

EOS_ASSERT( !name.empty(), action_validate_exception, "account name cannot be empty" );
EOS_ASSERT( name_str.size() <= 12, action_validate_exception, "account names can only be 12 chars long" );

// system account only can be created by newaccount
EOS_ASSERT( name_str.find( "eosio." ) != 0, action_validate_exception,
"only newaccount action can create account with name start with 'eosio.'" );

auto existing_account = db.find<account_object, by_name>(name);
EOS_ASSERT(existing_account == nullptr, account_name_exists_exception,
"Cannot create account named ${name}, as that name is already taken",
("name", name));

db.create<account_object>([&](auto& a) {
a.name = name;
a.creation_date = context.control.pending_block_time();
});

for (const auto& a : active_auth.accounts) {
auto* acct = context.db.find<account_object, by_name>(a.permission.actor);
EOS_ASSERT( acct != nullptr, action_validate_exception,
"account '${account}' does not exist",
("account", a.permission.actor)
);
if( a.permission.permission == config::active_name )
continue; // account was already checked to exist, so its active permissions should exist

if( a.permission.permission == config::eosio_code_name ) // virtual eosio.code permission does not really exist but is allowed
continue;

try {
context.control.get_authorization_manager().get_permission({a.permission.actor, a.permission.permission});
} catch( const permission_query_exception& ) {
EOS_THROW( action_validate_exception,
"permission '${perm}' does not exist",
("perm", a.permission)
);
}
}

const auto& active_permission = authorization.create_permission( name, config::active_name, 0,
std::move(active_auth), context.trx_context.is_transient() );
int64_t ram_delta = config::overhead_per_account_ram_bytes;
ram_delta -= config::billable_size_v<account_metadata_object>;
ram_delta += config::billable_size_v<permission_object>;
ram_delta += active_permission.auth.get_billable_size();
context.control.get_mutable_resource_limits_manager().initialize_account(name, context.trx_context.is_transient());

if (auto dm_logger = context.control.get_deep_mind_logger(context.trx_context.is_transient())) {
dm_logger->on_ram_trace(RAM_EVENT_ID("${name}", ("name", name)), "account", "add", "newslimacc");
}

context.add_ram_usage(name, ram_delta);
}
}}} // ns eosio::chain::webassembly
1 change: 0 additions & 1 deletion libraries/chain/webassembly/runtimes/eos-vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ REGISTER_LEGACY_HOST_FUNCTION(get_blockchain_parameters_packed, privileged_check
REGISTER_LEGACY_HOST_FUNCTION(set_blockchain_parameters_packed, privileged_check);
REGISTER_HOST_FUNCTION(is_privileged, privileged_check);
REGISTER_HOST_FUNCTION(set_privileged, privileged_check);
REGISTER_LEGACY_HOST_FUNCTION(create_slim_account, privileged_check);

// softfloat api
REGISTER_INJECTED_HOST_FUNCTION(_eosio_f32_add);
Expand Down
5 changes: 5 additions & 0 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ namespace eosio { namespace testing {
bool multisig = false,
bool include_code = true
);
transaction_trace_ptr create_slim_account( account_name name,
account_name creator = config::system_account_name,
bool multisig = false,
bool include_code = true
);
transaction_trace_ptr push_reqauth( account_name from, const vector<permission_level>& auths, const vector<private_key_type>& keys );
transaction_trace_ptr push_reqauth(account_name from, string role, bool multi_sig = false);
// use when just want any old non-context free action
Expand Down
33 changes: 33 additions & 0 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,39 @@ namespace eosio { namespace testing {
return push_transaction( trx );
}

transaction_trace_ptr base_tester::create_slim_account( account_name a, account_name creator, bool multisig, bool include_code ) {
signed_transaction trx;
set_transaction_headers(trx);

authority active_auth( get_public_key( a, "active" ) );

auto sort_permissions = []( authority& auth ) {
std::sort( auth.accounts.begin(), auth.accounts.end(),
[]( const permission_level_weight& lhs, const permission_level_weight& rhs ) {
return lhs.permission < rhs.permission;
}
);
};

if( include_code ) {
FC_ASSERT( active_auth.threshold <= std::numeric_limits<weight_type>::max(), "threshold is too high" );
active_auth.accounts.push_back( permission_level_weight{ {a, config::eosio_code_name},
static_cast<weight_type>(active_auth.threshold) } );
sort_permissions(active_auth);
}

trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
newslimacc{
.creator = creator,
.name = a,
.active = active_auth,
});

set_transaction_headers(trx);
trx.sign( get_private_key( creator, "active" ), control->get_chain_id() );
return push_transaction( trx );
}

transaction_trace_ptr base_tester::push_transaction( packed_transaction& trx,
fc::time_point deadline,
uint32_t billed_cpu_time_us
Expand Down
68 changes: 68 additions & 0 deletions unittests/abi_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,74 @@ BOOST_AUTO_TEST_CASE(newaccount_test)

} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE(newslimacc_test)
{ try {

abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time ));

BOOST_CHECK(true);
const char* test_data = R"=====(
{
"creator" : "newacct.crtr",
"name" : "newacct.name",
"active" : {
"threshold" : 2146483145,
"keys" : [ {"key" : "EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im", "weight" : 57005},
{"key" : "EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf", "weight" : 57605} ],
"accounts" : [ {"permission" : {"actor" : "prm.acct1", "permission" : "prm.prm1"}, "weight" : 53005 },
{"permission" : {"actor" : "prm.acct2", "permission" : "prm.prm2"}, "weight" : 53405 }],
"waits" : []
} }
)=====";

auto var = fc::json::from_string(test_data);

auto newslimacct = var.as<newslimacc>();
BOOST_TEST(name("newacct.crtr") == newslimacct.creator);
BOOST_TEST(name("newacct.name") == newslimacct.name);

BOOST_TEST(2146483145u == newslimacct.active.threshold);

BOOST_TEST_REQUIRE(2u == newslimacct.active.keys.size());
BOOST_TEST("EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im" == newslimacct.active.keys[0].key.to_string({}));
BOOST_TEST(57005u == newslimacct.active.keys[0].weight);
BOOST_TEST("EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf" == newslimacct.active.keys[1].key.to_string({}));
BOOST_TEST(57605u == newslimacct.active.keys[1].weight);

BOOST_TEST_REQUIRE(2u == newslimacct.active.accounts.size());
BOOST_TEST(name("prm.acct1") == newslimacct.active.accounts[0].permission.actor);
BOOST_TEST(name("prm.prm1") == newslimacct.active.accounts[0].permission.permission);
BOOST_TEST(53005u == newslimacct.active.accounts[0].weight);
BOOST_TEST(name("prm.acct2") == newslimacct.active.accounts[1].permission.actor);
BOOST_TEST(name("prm.prm2") == newslimacct.active.accounts[1].permission.permission);
BOOST_TEST(53405u == newslimacct.active.accounts[1].weight);


auto var2 = verify_byte_round_trip_conversion( abis, "newslimacc", var );
auto newslimacc2 = var2.as<newslimacc>();
BOOST_TEST(newslimacct.creator == newslimacc2.creator);
BOOST_TEST(newslimacct.name == newslimacc2.name);

BOOST_TEST(newslimacct.active.threshold == newslimacc2.active.threshold);

BOOST_TEST_REQUIRE(newslimacct.active.keys.size() == newslimacc2.active.keys.size());
BOOST_TEST(newslimacct.active.keys[0].key == newslimacc2.active.keys[0].key);
BOOST_TEST(newslimacct.active.keys[0].weight == newslimacc2.active.keys[0].weight);
BOOST_TEST(newslimacct.active.keys[1].key == newslimacc2.active.keys[1].key);
BOOST_TEST(newslimacct.active.keys[1].weight == newslimacc2.active.keys[1].weight);

BOOST_TEST_REQUIRE(newslimacct.active.accounts.size() == newslimacc2.active.accounts.size());
BOOST_TEST(newslimacct.active.accounts[0].permission.actor == newslimacc2.active.accounts[0].permission.actor);
BOOST_TEST(newslimacct.active.accounts[0].permission.permission == newslimacc2.active.accounts[0].permission.permission);
BOOST_TEST(newslimacct.active.accounts[0].weight == newslimacc2.active.accounts[0].weight);
BOOST_TEST(newslimacct.active.accounts[1].permission.actor == newslimacc2.active.accounts[1].permission.actor);
BOOST_TEST(newslimacct.active.accounts[1].permission.permission == newslimacc2.active.accounts[1].permission.permission);
BOOST_TEST(newslimacct.active.accounts[1].weight == newslimacc2.active.accounts[1].weight);


verify_type_round_trip_conversion<newslimacc>( abis, "newslimacc", var);

} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE(setcode_test)
{ try {
Expand Down
Loading

0 comments on commit 4a176cb

Please sign in to comment.