0LNetworkCommunity / libra-framework

9 stars 32 forks source link

Last Validator No Rewards #244

Open Barmaley8971 opened 4 months ago

Barmaley8971 commented 4 months ago

Describe the bug The last validator to join the active set doesn't receive the daily reward.

To Reproduce Steps to reproduce the behavior:

  1. Create a new validator.
  2. Enter the bid equivalent to the lowest bid in the active set.
  3. Get 2+ vouches from other validators.
  4. Join the active set.
  5. After 1 epoch, observe being charged the Fee (POF).
  6. Observe not receiving daily reward. Other validators receive their rewards.

Expected behavior In step 6 above, the validator should receive a reward.

Screenshots image This validator joined the active set last epoch. No reward, just the participation fee 3.2 0L charge. image This validator joined the active set 2 epochs ago. Did not receive the reward after the first epoch but did receive 320-3.2=316.8 after the second epoch.

Desktop (please complete the following information):

Smartphone (please complete the following information):

Additional context Add any other context about the problem here.

soaresa commented 2 months ago

Issue #251: Problems and Solutions at Epoch Boundary

Identified Problems

  1. Validator Reward Payment: The current check during reward payment skips the last validator if there is still budget remaining. This is because the check uses > instead of >=:

    epoch_boundary::process_outgoing_validators
    …
    if (libra_coin::value(reward_budget) > reward_per) {
        let user_coin = libra_coin::extract(reward_budget, reward_per);
        reward_deposited = reward_deposited + libra_coin::value(&user_coin);
        rewards::process_single(root, *addr, user_coin, 1);
    };
    …
  2. Subsidy Allocation Timing: proof_of_fee::reward_thermostat executes before the subsidy allocation for the next epoch's validator payment. If the thermostat increases the reward, there may not be enough subsidy to cover payments.

  3. Precision in Pledged Accounts: There is an issue with the precision in calculating the percentage of coins to be collected from each pledged account to form the subsidy in pledged_accounts::withdraw_from_all_pledge_accounts. This can result in a shortfall of one coin for the last validator.

  4. Allocation for Extra Validator: An unnecessary allocation for an extra validator intended for miners in the past is still present. This allocation is insufficient to cover all validators in the scenario of increased rewards and confuses epoch boundary status data.

  5. Entry Fee Calculation: The entry fee is calculated using fixed_point32::multiply_u64, resulting in a precision issue where the fee is one coin cheaper than expected due to rounding errors.

Proposed Solutions

  1. Adjust Reward Payment Check: Use >= instead of > to avoid skipping the last payment.

    if (libra_coin::value(reward_budget) >= reward_per) {
  2. Change Execution Order: Execute thermostat_reward before subsidy allocation to ensure sufficient funds for validator payments.

  3. Request Additional Amount: Request amount + 1 to address rounding issues and ensure accurate percentage sums from pledged accounts.

  4. Remove Extra Validator Allocation: Eliminate the allocation for an extra validator.

  5. Fix Entry Fee Calculation: Use a calculation method that avoids rounding errors and rounds down for periodic fractions.

soaresa commented 2 months ago

The function proof_of_fee::reward_thermostat has been refactored to move the reward calculation logic into a pure function. Additionally, the query proof_of_fee::query_reward_adjustment was created to use this pure function and provide information on the reward for the next epoch.