提交 758e539c 编写于 作者: A arhag

contracts are now only granted a virtual permission of "eosio.code"

A contract no longer satisfies all permissions of its account by default.

If a contract needs to be able send an inline action or deferred transaction and requires adding some specific permission to the authorizations of the action, then the authority of that permission must be set up in such a way that it can be satisfied by just the "eosio.code" permission.
上级 3293b5f5
......@@ -212,7 +212,7 @@ void apply_context::execute_inline( action&& a ) {
control.get_authorization_manager()
.check_authorization( {a},
{},
{{receiver, permission_name()}},
{{receiver, config::eosio_code_name}},
control.pending_block_time() - trx_context.published,
std::bind(&apply_context::checktime, this, std::placeholders::_1),
false
......@@ -270,7 +270,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
control.get_authorization_manager()
.check_authorization( trx.actions,
{},
{{receiver, permission_name()}},
{{receiver, config::eosio_code_name}},
delay,
std::bind(&apply_context::checktime, this, std::placeholders::_1),
false
......
......@@ -36,8 +36,26 @@ uint128_t transaction_id_to_sender_id( const transaction_id_type& tid ) {
void validate_authority_precondition( const apply_context& context, const authority& auth ) {
for(const auto& a : auth.accounts) {
context.db.get<account_object, by_name>(a.permission.actor);
context.control.get_authorization_manager().get_permission({a.permission.actor, a.permission.permission});
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::owner_name || a.permission.permission == config::active_name )
continue; // account was already checked to exist, so its owner and 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)
);
}
}
}
......@@ -74,10 +92,6 @@ void apply_eosio_newaccount(apply_context& context) {
"Cannot create account named ${name}, as that name is already taken",
("name", create.name));
for( const auto& auth : { create.owner, create.active, create.recovery } ){
validate_authority_precondition( context, auth );
}
const auto& new_account = db.create<account_object>([&](auto& a) {
a.name = create.name;
a.creation_date = context.control.pending_block_time();
......@@ -87,6 +101,10 @@ void apply_eosio_newaccount(apply_context& context) {
a.name = create.name;
});
for( const auto& auth : { create.owner, create.active, create.recovery } ){
validate_authority_precondition( context, auth );
}
const auto& owner_permission = authorization.create_permission( create.name, config::owner_name, 0,
std::move(create.owner) );
const auto& active_permission = authorization.create_permission( create.name, config::active_name, owner_permission.id,
......
......@@ -30,6 +30,7 @@ const static uint64_t eosio_all_scope = N(eosio.all);
const static uint64_t active_name = N(active);
const static uint64_t owner_name = N(owner);
const static uint64_t eosio_any_name = N(eosio.any);
const static uint64_t eosio_code_name = N(eosio.code);
const static int block_interval_ms = 500;
const static int block_interval_us = block_interval_ms*1000;
......
......@@ -116,10 +116,14 @@ namespace eosio { namespace testing {
uint32_t expiration = DEFAULT_EXPIRATION_DELTA,
uint32_t delay_sec = 0)const;
vector<transaction_trace_ptr> create_accounts( vector<account_name> names, bool multisig = false ) {
vector<transaction_trace_ptr> create_accounts( vector<account_name> names,
bool multisig = false,
bool include_code = true
)
{
vector<transaction_trace_ptr> traces;
traces.reserve(names.size());
for( auto n : names ) traces.emplace_back(create_account(n, config::system_account_name, multisig ));
for( auto n : names ) traces.emplace_back( create_account( n, config::system_account_name, multisig, include_code ) );
return traces;
}
......@@ -136,7 +140,11 @@ namespace eosio { namespace testing {
void delete_authority( account_name account, permission_name perm, const vector<permission_level>& auths, const vector<private_key_type>& keys );
void delete_authority( account_name account, permission_name perm );
transaction_trace_ptr create_account( account_name name, account_name creator = config::system_account_name, bool multisig = false );
transaction_trace_ptr create_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);
......@@ -173,7 +181,7 @@ namespace eosio { namespace testing {
void set_code( account_name name, const char* wast, const private_key_type* signer = nullptr );
void set_code( account_name name, const vector<uint8_t> wasm, const private_key_type* signer = nullptr );
void set_abi( account_name name, const char* abi_json, const private_key_type* signer = nullptr );
void set_abi( account_name name, const char* abi_json, const private_key_type* signer = nullptr );
bool chain_has_transaction( const transaction_id_type& txid ) const;
const transaction_receipt& get_transaction_receipt( const transaction_id_type& txid ) const;
......
......@@ -183,24 +183,45 @@ namespace eosio { namespace testing {
}
transaction_trace_ptr base_tester::create_account( account_name a, account_name creator, bool multisig ) {
transaction_trace_ptr base_tester::create_account( account_name a, account_name creator, bool multisig, bool include_code ) {
signed_transaction trx;
set_transaction_headers(trx);
authority owner_auth;
if (multisig) {
if( multisig ) {
// multisig between account's owner key and creators active permission
owner_auth = authority(2, {key_weight{get_public_key( a, "owner" ), 1}}, {permission_level_weight{{creator, config::active_name}, 1}});
} else {
owner_auth = authority( get_public_key( a, "owner" ) );
}
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( owner_auth.threshold <= std::numeric_limits<weight_type>::max(), "threshold is too high" );
FC_ASSERT( active_auth.threshold <= std::numeric_limits<weight_type>::max(), "threshold is too high" );
owner_auth.accounts.push_back( permission_level_weight{ {a, config::eosio_code_name},
static_cast<weight_type>(owner_auth.threshold) } );
sort_permissions(owner_auth);
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}},
newaccount{
.creator = creator,
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.active = active_auth,
.recovery = authority( get_public_key( a, "recovery" ) ),
});
......
......@@ -303,14 +303,14 @@ try {
// Verify account created properly
const auto& joe_owner_authority = chain.get<permission_object, by_owner>(boost::make_tuple("joe", "owner"));
BOOST_TEST(joe_owner_authority.auth.threshold == 1);
BOOST_TEST(joe_owner_authority.auth.accounts.size() == 0);
BOOST_TEST(joe_owner_authority.auth.accounts.size() == 1);
BOOST_TEST(joe_owner_authority.auth.keys.size() == 1);
BOOST_TEST(string(joe_owner_authority.auth.keys[0].key) == string(chain.get_public_key("joe", "owner")));
BOOST_TEST(joe_owner_authority.auth.keys[0].weight == 1);
const auto& joe_active_authority = chain.get<permission_object, by_owner>(boost::make_tuple("joe", "active"));
BOOST_TEST(joe_active_authority.auth.threshold == 1);
BOOST_TEST(joe_active_authority.auth.accounts.size() == 0);
BOOST_TEST(joe_active_authority.auth.accounts.size() == 1);
BOOST_TEST(joe_active_authority.auth.keys.size() == 1);
BOOST_TEST(string(joe_active_authority.auth.keys[0].key) == string(chain.get_public_key("joe", "active")));
BOOST_TEST(joe_active_authority.auth.keys[0].weight == 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册