Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release v1.0.3 to master #15

Merged
merged 24 commits into from
Dec 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ set( CXX_STANDARD_REQUIRED ON)

set(VERSION_MAJOR 1)
set(VERSION_MINOR 0)
set(VERSION_PATCH 2)
set(VERSION_PATCH 3)

set( CLI_CLIENT_EXECUTABLE_NAME cleos )
set( NODE_EXECUTABLE_NAME nodeos )
Expand Down
4 changes: 2 additions & 2 deletions Docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ cd bos/Docker
docker build . -t boscore/bos
```

The above will build off the most recent commit to the master branch by default. If you would like to target a specific branch/tag, you may use a build argument. For example, if you wished to generate a docker image based off of the v1.0.2 tag, you could do the following:
The above will build off the most recent commit to the master branch by default. If you would like to target a specific branch/tag, you may use a build argument. For example, if you wished to generate a docker image based off of the v1.0.3 tag, you could do the following:

```bash
docker build -t boscore/bos:v1.0.2 --build-arg branch=v1.0.2 .
docker build -t boscore/bos:v1.0.3 --build-arg branch=v1.0.3 .
```

By default, the symbol in eosio.system is set to SYS. You can override this using the symbol argument while building the docker image.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# BOSCore - Born for DApp, be more useable.
# BOSCore - Born for DApps. Born for Usability.

## BOSCore Version: v1.0.2
## BOSCore Version: v1.0.3
### Basic EOSIO Version: v1.4.4

# Background
Expand Down
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# BOSCore - 更可用的链,为DApp而生。

## BOSCore Version: v1.0.2
## BOSCore Version: v1.0.3
### Basic EOSIO Version: v1.4.4

# 背景
Expand Down
108 changes: 85 additions & 23 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,29 +209,61 @@ void apply_context::execute_inline( action&& a ) {
EOS_ASSERT( code != nullptr, action_validate_exception,
"inline action's code account ${account} does not exist", ("account", a.account) );

bool disallow_send_to_self_bypass = false; // eventually set to whether the appropriate protocol feature has been activated
bool send_to_self = (a.account == receiver);
bool inherit_parent_authorizations = (!disallow_send_to_self_bypass && send_to_self && (receiver == act.account) && control.is_producing_block());

flat_set<permission_level> inherited_authorizations;
if( inherit_parent_authorizations ) {
inherited_authorizations.reserve( a.authorization.size() );
}

for( const auto& auth : a.authorization ) {
auto* actor = control.db().find<account_object, by_name>(auth.actor);
EOS_ASSERT( actor != nullptr, action_validate_exception,
"inline action's authorizing actor ${account} does not exist", ("account", auth.actor) );
EOS_ASSERT( control.get_authorization_manager().find_permission(auth) != nullptr, action_validate_exception,
"inline action's authorizations include a non-existent permission: ${permission}",
("permission", auth) );

if( inherit_parent_authorizations && std::find(act.authorization.begin(), act.authorization.end(), auth) != act.authorization.end() ) {
inherited_authorizations.insert( auth );
}
}

// No need to check authorization if: replaying irreversible blocks; contract is privileged; or, contract is calling itself.
if( !control.skip_auth_check() && !privileged && a.account != receiver ) {
control.get_authorization_manager()
.check_authorization( {a},
{},
{{receiver, config::eosio_code_name}},
control.pending_block_time() - trx_context.published,
std::bind(&transaction_context::checktime, &this->trx_context),
false
);

//QUESTION: Is it smart to allow a deferred transaction that has been delayed for some time to get away
// with sending an inline action that requires a delay even though the decision to send that inline
// action was made at the moment the deferred transaction was executed with potentially no forewarning?
// No need to check authorization if replaying irreversible blocks or contract is privileged
if( !control.skip_auth_check() && !privileged ) {
try {
control.get_authorization_manager()
.check_authorization( {a},
{},
{{receiver, config::eosio_code_name}},
control.pending_block_time() - trx_context.published,
std::bind(&transaction_context::checktime, &this->trx_context),
false,
inherited_authorizations
);

//QUESTION: Is it smart to allow a deferred transaction that has been delayed for some time to get away
// with sending an inline action that requires a delay even though the decision to send that inline
// action was made at the moment the deferred transaction was executed with potentially no forewarning?
} catch( const fc::exception& e ) {
if( disallow_send_to_self_bypass || !send_to_self ) {
throw;
} else if( control.is_producing_block() ) {
subjective_block_production_exception new_exception(FC_LOG_MESSAGE( error, "Authorization failure with inline action sent to self"));
for (const auto& log: e.get_log()) {
new_exception.append_log(log);
}
throw new_exception;
}
} catch( ... ) {
if( disallow_send_to_self_bypass || !send_to_self ) {
throw;
} else if( control.is_producing_block() ) {
EOS_THROW(subjective_block_production_exception, "Unexpected exception occurred validating inline action sent to self");
}
}
}

_inline_actions.emplace_back( move(a) );
Expand Down Expand Up @@ -268,16 +300,30 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
require_authorization(payer); /// uses payer's storage
}

// if a contract is deferring only actions to itself then there is no need
// to check permissions, it could have done everything anyway.
bool check_auth = false;
for( const auto& act : trx.actions ) {
if( act.account != receiver ) {
check_auth = true;
break;
// Originally this code bypassed authorization checks if a contract was deferring only actions to itself.
// The idea was that the code could already do whatever the deferred transaction could do, so there was no point in checking authorizations.
// But this is not true. The original implementation didn't validate the authorizations on the actions which allowed for privilege escalation.
// It would make it possible to bill RAM to some unrelated account.
// Furthermore, even if the authorizations were forced to be a subset of the current action's authorizations, it would still violate the expectations
// of the signers of the original transaction, because the deferred transaction would allow billing more CPU and network bandwidth than the maximum limit
// specified on the original transaction.
// So, the deferred transaction must always go through the authorization checking if it is not sent by a privileged contract.
// However, the old logic must still be considered because it cannot objectively change until a consensus protocol upgrade.

bool disallow_send_to_self_bypass = false; // eventually set to whether the appropriate protocol feature has been activated

auto is_sending_only_to_self = [&trx]( const account_name& self ) {
bool send_to_self = true;
for( const auto& act : trx.actions ) {
if( act.account != self ) {
send_to_self = false;
break;
}
}
}
if( check_auth ) {
return send_to_self;
};

try {
control.get_authorization_manager()
.check_authorization( trx.actions,
{},
Expand All @@ -286,6 +332,22 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
std::bind(&transaction_context::checktime, &this->trx_context),
false
);
} catch( const fc::exception& e ) {
if( disallow_send_to_self_bypass || !is_sending_only_to_self(receiver) ) {
throw;
} else if( control.is_producing_block() ) {
subjective_block_production_exception new_exception(FC_LOG_MESSAGE( error, "Authorization failure with sent deferred transaction consisting only of actions to self"));
for (const auto& log: e.get_log()) {
new_exception.append_log(log);
}
throw new_exception;
}
} catch( ... ) {
if( disallow_send_to_self_bypass || !is_sending_only_to_self(receiver) ) {
throw;
} else if( control.is_producing_block() ) {
EOS_THROW(subjective_block_production_exception, "Unexpected exception occurred validating sent deferred transaction consisting only of actions to self");
}
}
}

Expand Down
11 changes: 7 additions & 4 deletions libraries/chain/authorization_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ namespace eosio { namespace chain {
const flat_set<permission_level>& provided_permissions,
fc::microseconds provided_delay,
const std::function<void()>& _checktime,
bool allow_unused_keys
bool allow_unused_keys,
const flat_set<permission_level>& satisfied_authorizations
)const
{
const auto& checktime = ( static_cast<bool>(_checktime) ? _checktime : _noop_checktime );
Expand Down Expand Up @@ -488,9 +489,11 @@ namespace eosio { namespace chain {
}
}

auto res = permissions_to_satisfy.emplace( declared_auth, delay );
if( !res.second && res.first->second > delay) { // if the declared_auth was already in the map and with a higher delay
res.first->second = delay;
if( satisfied_authorizations.find( declared_auth ) == satisfied_authorizations.end() ) {
auto res = permissions_to_satisfy.emplace( declared_auth, delay );
if( !res.second && res.first->second > delay) { // if the declared_auth was already in the map and with a higher delay
res.first->second = delay;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ namespace eosio { namespace chain {
const flat_set<permission_level>& provided_permissions = flat_set<permission_level>(),
fc::microseconds provided_delay = fc::microseconds(0),
const std::function<void()>& checktime = std::function<void()>(),
bool allow_unused_keys = false
bool allow_unused_keys = false,
const flat_set<permission_level>& satisfied_authorizations = flat_set<permission_level>()
)const;


Expand Down