-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enrich staking metadata exports (#786)
Signed-off-by: Michael Tinker <michael.tinker@swirldslabs.com> Co-authored-by: Michael Garber <michael.garber@swirldslabs.com>
- Loading branch information
1 parent
ef0eec7
commit f89b8d3
Showing
1 changed file
with
185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
--- | ||
hip: 786 | ||
title: Enriched staking metadata exports | ||
author: Michael Tinker <michael.tinker@swirldslabs.com> | ||
working-group: Leemon Baird <leemon@swirldslabs.com>, Alex Popowycz <a@hedera.com> | ||
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) |