diff --git a/HIP/hip-786.md b/HIP/hip-786.md new file mode 100644 index 000000000..d19be1e0d --- /dev/null +++ b/HIP/hip-786.md @@ -0,0 +1,185 @@ +--- +hip: 786 +title: Enriched staking metadata exports +author: Michael Tinker +working-group: Leemon Baird , Alex Popowycz +type: Standards Track +category: Core +needs-council-approval: Yes +status: Review +created: 2023-08-10 +discussions-to: https://github.com/hashgraph/hedera-improvement-proposal/discussions/785 +updated: 2023-08-11 +--- + +## Abstract + +The Hedera network pays staking rewards using an opportunistic mechanism defined by [HIP-406](https://hips.hedera.com/hip/hip-406). +When an account is involved in a transaction that changes its staked amount or staking metadata, it automatically receives +any rewards it has earned from the `0.0.800` account. + +This means we cannot interpret the `0.0.800` balance as the amount of staking rewards that could still be earned in the +future. We have to recognize that part of this balance is **reserved** for staking rewards that are already earned, +but not yet paid. Furthermore, only the **unreserved** part of the `0.0.800` balance at the end of a staking period +affects the reward rate that will be paid for that period; c.f. [HIP-782](https://hips.hedera.com/hip/hip-782). + +In principle, anyone can compute the reserved rewards by iterating through each account's staking metadata and computing +its pending rewards. By tracking the end-of-period `0.0.800` balance and current network properties, they can then compute +the unreserved `0.0.800` balance and the HIP-782 reward rate for that period. But this is an exorbitant amount of work, +and consensus nodes could just as easily expose all this information directly to mirror nodes via the end-of-period +`NodeStakeUpdateTransactionBody` transaction. + +Hence we propose adding four fields to the `NodeStakeUpdateTransactionBody` transaction: + 1. `reserved_staking_rewards` - the total staking rewards earned but not collected at the close of the previous staking period. + 2. `unreserved_staking_reward_balance` - the funds available for future staking rewards at the close of the previous period. + 3. `reward_balance_threshold` - as defined in [HIP-782](https://hips.hedera.com/hip/hip-782). + 4. `max_stake_rewarded` - as defined in [HIP-782](https://hips.hedera.com/hip/hip-782). + +We also propose deprecating the [`staking_reward_rate`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/node_stake_update.proto#L82) +field, and replacing it with a new field `total_reward`. This replacement field will have the same information---that is, the total +number of tinybars to be paid as staking rewards for the just-ended period. But its new name will avoid confusing readers who are +not familiar with the revision history of HIP-406. (The legacy `staking_reward_rate` field will continue to be populated for an +appropriate time.) + +We recommend that relevant mirror node APIs (such as the Hedera public mirror node endpoint `/api/v1/network/stake`) expand to +include these new fields. + +## Motivation + +Stakers and other interested parties might like to know the reserved rewards, `0.0.800` unreserved balance, and HIP-782 properties +for any number of reasons; for example, to estimate the rewards they might receive from staking, or to confirm the observed reward +rate matches the formula in HIP-782. + +## Rationale + +Since we already export many other important staking values in the end-of-period synthetic +[`NodeStakeTransactionBody`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/node_stake_update.proto#L35), +it is hard to find a reason to put these related values anywhere else. + +## User stories + +As an HBAR staker, I want to follow along from home as the network applies the HIP-782 reward rate formulas. + +As a mirror node operator, I want to give my API clients an up-to-date view on the amount of reserved rewards. + +As a Hedera council member, I want to make decisions about network staking parameters based on the unreserved `0.0.800` balance. + +## Specification + +### Consensus nodes + +Update the [`NodeStakeTransactionBody`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/node_stake_update.proto#L35) +with fields the consensus nodes will use to export all the staking values in HIP-782 formulas, as below: +``` +message NodeStakeUpdateTransactionBody { + ... + /** + * (DEPRECATED) The total number of tinybars to be distributed as staking rewards each period. + * Please consult the total_reward field instead. + */ + int64 staking_reward_rate = 9 [deprecated = true]; + + /** + * The amount of the staking reward funds (account 0.0.800) reserved to pay pending rewards that + * have been earned but not collected. + */ + int64 reserved_staking_rewards = 10; + + /** + * The unreserved balance of account 0.0.800 at the close of the just-ending period; this value is + * used to compute the HIP-782 balance ratio. + */ + int64 unreserved_staking_reward_balance = 11; + + /** + * The unreserved tinybar balance of account 0.0.800 required to achieve the maximum per-hbar reward + * rate; please see HIP-782 for details. + */ + int64 reward_balance_threshold = 12; + + /** + * The maximum amount of tinybar that can be staked for reward while still achieving the maximum + * per-hbar reward rate; please see HIP-782 for details. + */ + int64 max_stake_rewarded = 13; + + /** + * The total tinybars to be paid as staking rewards in the ending period, after applying + * the settings for the 0.0.800 balance threshold and the maximum stake rewarded. + */ + int64 total_reward = 14; +} +``` + +### Mirror nodes + +If a mirror node API exposes network staking properties, it _should_ expand to include this new information +and _should_ replace the `staking_reward_rate` field with `total_reward`. For example, +the Hedera public mirror node currently exposes a `/api/v1/network/stake` endpoint with sample response, +``` +{ + "max_staking_reward_rate_per_hbar": 17808, + "node_reward_fee_fraction": 0, + "stake_total": 3420441313766831000, + "staking_period": { + "from": "1691625600.000000000", + "to": "1691712000.000000000" + }, + "staking_period_duration": 1440, + "staking_periods_stored": 365, + "staking_reward_fee_fraction": 0, + "staking_reward_rate": 273972602739726, + "staking_start_threshold": 25000000000000000 +} +``` + +This response should remove the `staking_reward_rate` mapping and expand to include, +``` +{ + ... + "reserved_staking_rewards": 111111111, + "unreserved_staking_reward_balance": 222222222, + "reward_balance_threshold": 333333333, + "max_stake_rewarded": 444444444, + "total_reward": 273972602739726 +} +``` + + +## Backwards Compatibility + +This HIP primarily adds new information that mirror node operators and other record stream consumers can simply ignore if +they do not need it. However, consumers of the `staking_reward_rate` field should migrate to use `total_reward` within +an appropriate time interval. + +## Security Implications + +There are no security implications for this HIP. It simply provides a much more convenient, aggregated view of +information that is already publicly available. + +## How to Teach This + +Mirror node operators can use newly exported fields to easily give a full picture of the HIP-782 staking formulas. + +## Reference Implementation + +Please follow [this issue](https://github.com/hashgraph/hedera-services/issues/7946) for progress on the reference implementation. + +## Rejected Ideas + +We briefly considered adding a consensus node query to give a real-time view into the reserved rewards and unreserved +`0.0.800` balance. But since these values are only _used_ once per staking period, there seemed very little value in doing so. + +## Open Issues + +No known open issues exist. + +## References + +1. [HIP-406](https://hips.hedera.com/hip/hip-406) +2. [HIP-782](https://hips.hedera.com/hip/hip-782) +3. [`NodeStakeTransactionBody`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/node_stake_update.proto#L35) + +## Copyright/license + +This document is licensed under the Apache License, Version 2.0 -- see [LICENSE](../LICENSE) or (https://www.apache.org/licenses/LICENSE-2.0)