Rectify inflation based on time instead of blocks

Background

Currently on mainnet blocks are produced usually at between 1.2 and 1.3 per second, which is great. However, when we calculate inflation per epoch, we use the following formula (note: this excludes the tokens burnt in transaction fees):

inflation = total_supply * yearly_inflate_rate * epoch_length / expected_num_blocks_per_year

where expected_num_blocks_per_year is a genesis parameter currently set to 31536000, i.e, a block every second. Since blocks are produced faster that, expected_num_blocks_per_year is smaller than the actual value, which means that, at the current rate, we will have ~20% more inflation than expected.

Proposal

Calculating the inflation based on blocks isn’t the most reliably way to begin with. Even though currently epochs are shorter than expected, they could, in some cases, be longer than expected if there are a few validators offline for the entire duration of the epoch. To address this, I propose that we change the inflation calculation based on time elapsed instead of number of blocks. More specifically, this proposal only requires changing the inflation calculation to

inflation = total_supply * yearly_inflation_rate * duration_of_epoch_in_seconds / num_seconds_in_a_year

This is essentially still a first-order Taylor approximation of the target inflation rate, in the similar vein as the original calculation. However, it is more accurate and is less subject to the perturbation of the epoch time.

6 Likes

Are there any oracle (or similar) type vulnerabilities with determining how many seconds are in an epoch or is it reliable? IIRC time is a rather tricky concept.

For example, wondering if time can be messed with by a malicious actor to modify the inflation they know they will receive in a future epoch, like convincing the system the last epoch was a full year long and collecting disproportionate rewards.

Anyway, to clarify details, would the calculation apply to the current epoch (so inflation is paid at its conclusion… not sure what actually happens currently) or for the following epoch?

Time is relatively reliable unless 2/3 of the validators collude because blocks will be rejected if its timestamp is outside the tolerable margin (2 min), so on the scale of an epoch (~12 hours) the inaccuracy doesn’t really matter.

It is always calculated and credited at the beginning of the following epoch. This part does not need to be changed.

Hey @Bowen, a time-based new-issuance calculation makes sense to me. This is an outstanding issue for us on the Cosmos Hub.

As an aside, it would be good to cross-post in https://gov.near.org/c/gov when the economic changes (or any other changes) will likely lead to a governance proposal.

1 Like

the consequences will be critical. IMO we shouldn’t live in the hope that 2/3 collusion is impossible. Rather need to look for solutions to reduce the harm from such a collusion and not implement solutions that increase the cartel’s profit stimulating collusion.

Agree.
What about any kind of combined approach?

inflation = total_supply * yearly_inflation_rate * min(epoch_length / expected_num_blocks_per_year, duration_of_epoch_in_seconds / num_seconds_in_a_year)
1 Like

Currently if 2/3 of validators collude they can commit invalid state transitions and mint tokens out of nowhere, which is much worse than messing up inflation.

@Bowen what’s the timeline for this proposal going to a vote?

We are conflating two types of the collusion:

  • Collusion to violate the protocol – malicious action;
  • Collusion to side-step the implementation details of the specific client – can be done without violating the protocol, in non-malicious, but selfish or foolish way, e.g. tweaking the client to reject state sync requests.

Tweaking the client to accept the blocks even outside the tolerable margin is a type of the selfish or foolish collision. It is not a protocol-level collision because if it was it would’ve been possible to construct a challenge, with time one cannot construct the challenge because it is subjective and depends on the clock of a specific client.

Validators actually have a selfish incentive to tweak the time to accept the blocks that have earlier timestamps than their OS clock, because it increases inflation. This action not only cannot prevented but they can also have a plausible deniability if done smartly. It is not a protocol-level collusion same as tweaking network or RPC service to reject large request is not a protocol-level collusion.

That is correct. However if that is the only thing they do, then it requires every single validator to do this to actually be effective. Even a single honest validator could restore the time since we require, on the protocol level, that block time be strictly monotonically increasing. So I am not sure whether it is a concern in practice.

I agree that we should base our inflation on real time rather than block height. The current system incentivizes block producers to produce blocks faster to get more rewards.

The benefit that block producers can gain by manipulating timestamp is very limited, as long as they can’t change the timestamp by too much. For example, if a block producer moves the timestamp of the last block in an epoch forward by two minutes, that epoch becomes longer by two minutes, but the next epoch becomes shorter by two minutes. As a result, if a block producer is in both epochs, their reward doesn’t change.

We can also change the node behavior to make timestamp manipulation even more difficult. To this end, I propose to make block producer nodes ignore blocks that have their timestamp in the future (compared to system clock) if they don’t have 2/3 approvals (which would allow producing a block on top of them). In particular, block producers themselves should not generate approvals for such blocks. If at least 1/3 of block producers follow this strategy, producing a block with a timestamp that is in the future will be equivalent to actually releasing it at that future time (and by that time, it can already be skipped). This also assumes that the operators of block producer nodes take care to maintain correct system time, which we probably expect them to do anyway.

We currently do not allow blocks to be produced with less than 2/3 approvals. Such blocks would be outright considered invalid and dropped. In addition, we already have a mechanism to reject blocks with timestamps in the future if the difference between the timestamp and local clock time is larger than some tolerable margin (currently set to 2 minutes).

By “have 2/3 approvals” I mean having 2/3 approvals for this block (these approvals will be included in the next block). The approvals included in a block are for the previous block.