Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

resource manager audit #3951

Merged
merged 5 commits into from
Jun 8, 2018

Conversation

wanderingbort
Copy link
Contributor

  • doing a ratio<> multiply now checks for overflow conditions. This is a safe assert to add to any chain with default parameters because:
    • ratio is used for elastic limits, the largest current use being max-block-cpu * max-virtual-cpu-mult * maximum-ratio aka 200,000 * 1000 * 1000 which is well under the 64bit limit
    • ratio is used to maintain an exponential moving average of usage, the largest current use being maximum-single-user-value * precision * window-size aka 200,000 * 1,000,000 * 172,800 which needs 55bits and therfore would not hit this assert
  • doing cast from uint128_t for math to uint64_t for results now asserts that the values are representable, for the same reasons as ratio<> this is safe with the defaults but added to protect against future deployments with significantly higher values
  • fixed a bug in the estimator of available cpu/net usage where our fixed point math ceiling divide was not taken into account. This would lead to situations where our cpu timers were a few microseconds off but because the final accounting would catch anything there was no ability for this to affect concensus. It is now just better at setting speculative limits

Also removed repetition between get_account* and get_account*_ex

 - doing a ratio<> multiply now checks for overflow conditions.  This is safe because:
    - ratio is used for elastic limits, the largest current use being max-block-cpu * max-virtual-cpu-mult * maximum-ratio aka 200,000 * 1000 * 1000 which is well under the 64bit limit
    - ratio is used to maintain an exponential moving average of usage, the largest current use being maximum-single-user-value * precision * window-size aka 200,000 * 1,000,000 * 172,800 which needs 55bits and therfore would not hit this assert
 - doing cast from uint128_t for math to uint64_t for results now asserts that the values are representable, for the same reasons as ratio<> this is safe with the defaults but added to protect against future deployments with significantly higher values
@wanderingbort wanderingbort requested a review from arhag June 8, 2018 16:00
@arhag arhag added this to the Version 1.0.2 milestone Jun 8, 2018
…ignedness matches. this prevents a potentially overflowing cast
@@ -16,13 +16,43 @@ namespace eosio { namespace chain { namespace resource_limits {

template<typename T>
T operator* (T value, const ratio<T>& r) {
EOS_ASSERT(std::numeric_limits<T>::max() / r.numerator >= value, rate_limiting_state_inconsistent, "Usage exceeds maximum value representable after extending for precision");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't r.numerator potentially be 0? The EOS_ASSERT should assert on the condition r.numerator == T() || std::numeric_limits<T>::max() / r.numerator >= value instead, assuming we can rely on T() representing the arithmetic zero value of the type T.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in current practice I dont think its ever zero but this is a fine additional check.

template<typename LesserIntType, typename GreaterIntType>
constexpr auto downgrade_cast(GreaterIntType val) ->
std::enable_if_t<std::is_signed<LesserIntType>::value == std::is_signed<GreaterIntType>::value, LesserIntType>
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be even nicer if all of these templated functions had static asserts to check that the template type is an integer type.

@@ -344,59 +349,6 @@ int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name
int64_t cpu_weight;
get_account_limits( name, unused, unused, cpu_weight );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer if you used two different variables for the unused arguments (similar to the x and y used in get_account_net_limit_ex), so that we don't get confusing by spooky aliasing behavior while debugging get_account_limits in the future.

@arhag arhag merged commit 4d90af7 into EOSIO:master Jun 8, 2018
@wanderingbort wanderingbort deleted the feature/resource-manager-audit branch June 8, 2018 20:57
@arhag arhag added the CONSENSUS Introduces a change that may modify consensus protocol rules on an existing blockchain. label Jun 8, 2018
@arhag
Copy link
Contributor

arhag commented Jun 8, 2018

We have determined that this change can actually prevent v1.0.2 from replaying a blockchain produced with v1.0.1.

This was verified by replaying the Jungle testnet blockchain and observing a discrepancy at block 388461.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
CONSENSUS Introduces a change that may modify consensus protocol rules on an existing blockchain.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants