Skip to content

Latest commit

 

History

History
465 lines (377 loc) · 18.5 KB

dcp-0012.mediawiki

File metadata and controls

465 lines (377 loc) · 18.5 KB

DCP: 0012
Title: Change PoW/PoS Subsidy Split To 1/89
Author: Dave Collins <davec@decred.org>
        Jake Yocom-Piatt
Status: Active
Created: 2023-04-13
License: CC0-1.0
License-Code: ISC
Requires: DCP0006
Replaces: DCP0010

Table of Contents

Abstract

This specifies modifications to the block reward subsidy split such that 1% goes to Proof-of-Work (PoW) and 89% goes to Proof-of-Stake (PoS). The Treasury subsidy remains at 10%.

Motivation

This proposal is the result of continued analysis after the previous subsidy split change made by DCP0010 which shows that the majority of the PoW hash power continues to be highly centralized and used to maliciously manipulate Decred markets.

The proposed modification, in tandem with changing the PoW hashing function as described in DCP0011, is intended break up the mining cartel and further improve decentralization of the issuance process.

See the Politeia proposal for further details.

Specification

Integer Math

In order to facilitate better compatibility across implementations and languages, the formulas defined by the specification make use of integer math instead of floating point math as denoted by the use of the floor function. This is highly desirable for consensus code since floating point math can be problematic across languages due to issues such as rounding errors and uncertainty in their respective libraries.

Full Block Subsidy Formula

The calculated full subsidy for each block MUST remain the same as it is prior to this specification. Since calculation of the modified subsidy proportions for PoW and PoS relies on first calculating the full subsidy, the details of the existing calculation are also provided in this specification.

Explanation of terms:

Sfull = The full block subsidy at a given height
h = The height for which the full subsidy is to be calculated
P = The coins generated by the first block (1,680,000 X 108 on mainnet)
I = The number of blocks in the subsidy reduction interval (6144 on mainnet)
c0 = The base coin subsidy before any reductions (3,119,582,664 on mainnet)
Rm = The coin subsidy reduction multiplier (100 on mainnet)
Rd = The coin subsidy reduction divisor (101 on mainnet)

Modified Subsidy Split

The subsidy split for the full block subsidy MUST be split between Proof-of-Work (PoW), Proof-of-Stake (PoS), and the decentralized Treasury as follows:

  • PoW - 1%
  • PoS - 89%
  • Treasury - 10% (no change from existing)
Additionally, the resulting PoS subsidy MUST be split evenly between the maximum number of votes per block, which, as of this specification, is 5 on all networks.

The Treasury subsidy proportion MUST remain the same and otherwise retain all existing semantics it has prior to this specification.

The following formulas precisely specify the calculations for the modified subsidy splits for arbitrary heights. This ensures the semantics are fully specified for all heights; however, it is important to note that they MUST only be applied to mainnet, and current testnet, for heights where the new rules are active per the associated on-chain vote.

Explanation of terms:

Sfull = The full block subsidy at a given height
Spow = The subsidy for proof of work at a given height for a given number of votes
Svote = The subsidy for a single vote at a given height
h = The height for which the subsidy is to be calculated
v = The number of votes included in the block
Hsv = The height at which stake validation begins (4096 on mainnet)
vb = The number of votes per block (5 on all networks)
vm = The minimum number of required votes (3 on all networks)

Subsidy Enforcement

IMPORTANT: The PoS subsidy, and hence each individual vote subsidy, is based on the block PRIOR to the one that contains the vote since that prior block is the one being voted on. In practice, this means the formula to calculate the vote subsidy MUST be called with a height of one less than the PoW subsidy formula once the height that voting begins at is reached.

The following modified rules MUST be enforced:

  • The input value of the one and only input of the coinbase transaction MUST commit to the modified PoW subsidy proportion
  • The total of the output values of the coinbase transaction MUST NOT exceed the modified PoW subsidy proportion plus the total fees from all transactions contained in the block
  • The input value of the stakebase of vote transactions MUST commit to the modified single vote subsidy proportion
  • The proportional payouts of vote transactions MUST be calculated based on the modified single vote subsidy proportion
  • The total of the output values of vote transactions MUST NOT exceed modified single vote subsidy proportion

Coinbase Rules and DCP0006 Requirement

The rule regarding the total of the output values of the coinbase transaction takes into account that DCP0006 is already active.

Rationale

As previously described in the Rationale section of DCP0010, Proof of Work is intended to provide several key properties to Decred, some of which are:

  • Unambiguous determination of the exact contents of a block
  • Unforgeable historical timestamps
  • A source of entropy
  • Significantly increased cost to conduct a wide variety of attacks
  • Protection against data manipulation and double spends
  • Fair coin distribution
While PoW has worked well for almost all of these properties, unfortunately extensive analysis has shown that the expected results of a fair coin distribution has not been achieved.

A commonly overlooked aspect of PoW mining is that it has to behave similarly to gold mining in order for it to achieve the expected results of a fair coin distribution. That is the reason the process is referred to as mining.

More concretely, the price is expected to track the cost of production such that, as the profitability goes up, the incentives for competition also go up which leads to more participants (hash power) and thus profitability reduces accordingly.

It is clear from further analysis that the previous adjustments to lower the PoW subsidy did not go far enough to achieve that expected result as evidenced by noting that despite the expected drop in the hash power relative to the levels prior to the previous adjustment, the same degree of PoW centralization is still present.

Moreover, it is extremely unlikely that further lowering the PoW subsidy in isolation will be able to spur increased decentralization because the specialized hardware the existing monopoly uses to mine was paid off from mining income long ago. Additionally, a lower subsidy makes the creation of any new specialized hardware that would be needed to break up the monopoly even less likely.

Therefore, the best remaining reasonable option is to both change the PoW hashing algorithm in order to obsolete the existing specialized hardware (defined in DCP0011) and simultaneously lower the subsidy even further per this specification. These two modifications in tandem are intended to break up the mining cartel and avoid continuing to overpay for what PoW provides under the new PoW hashing algorithm.

This approach allows Decred to retain the positive parts of PoW, like it being an entropy source and providing unforgeable costliness and irreversibility.

Deployment

Voting Agenda Parameters

This proposal will be deployed to mainnet using the standard Decred on-chain voting infrastructure as follows:

Name Setting
Deployment Version 10
Agenda ID changesubsidysplitr2
Agenda Description Change block reward subsidy split to 1/89/10 as defined in DCP0012
Start Time 1682294400 (Apr 24th, 2023 00:00:00 +0000 UTC)
Expire Time 1745452800 (Apr 24th, 2025 00:00:00 +0000 UTC)
Mask 0x0060 (Bits 5 and 6)
Choices
Choice English Description Bits
abstain abstain voting for change 0x00
no keep the existing consensus rules 0x0020 (Bit 5)
yes change to the new consensus rules 0x0040 (Bit 6)

Voting Results

This proposal was approved by the stakeholder voting process and is now active.

Status Block Hash Block Height
Voting Started 0000000000000000d608dc4ec7fcae5c650353db68a77f2954df74c25462f337 778240
Locked In 0000000000000000896042b2b0536a4046e56ef505f20f7301ca7e042a5c218e 786304
Active 071683030010299ab13f139df59dc98d637957b766e47f8da6dd5ac762f1e8c7 794368

Compatibility

This is a hard-forking change to the Decred consensus. This means that once the agenda is voted in and becomes locked in, anybody running code that fully validates blocks must upgrade before the activation time or they will reject all blocks containing transactions with payouts that conform to the new subsidy split since they are invalid under the old rules.

Other software that performs full validation will need to modify their consensus enforcement rules accordingly and any software that creates coinbases or votes will need to be updated to handle the changes specified herein.

Reference Implementation

The following implementations are simplified versions intended to clearly illustrate the exact semantics of this specification with self-contained functions. See the linked pull request for the full implementations that include optimizations and the ability to selectively calculate both the legacy subsidy proportions as well as the new ones defined herein.

Full Block Subsidy Calculation

// calcBlockSubsidy returns the max potential subsidy for a block at the
// provided height.  This value is reduced over time based on the height and
// then split proportionally between PoW, PoS, and the Treasury.
func calcBlockSubsidy(height int64) int64 {
	// These parameters are ordinarily unique per chain and thus should be
	// passed into the function via a chain parameters structure, however,
	// they are defined as constants with the mainnet parameters here for the
	// purposes of providing a self-contained function for the DCP.
	const (
		mainnetBlockOneSubsidy            = 1680000 * 100000000
		mainnetSubsidyReductionInterval   = 6144
		mainnetBaseSubsidy                = 3119582664
		mainnetSubsidyReductionMultiplier = 100
		mainnetSubsidyReductionDivisor    = 101
	)

	// Negative block heights are invalid and produce no subsidy.
	// Block 0 is the genesis block and produces no subsidy.
	// Block 1 subsidy is special as it is used for initial token distribution.
	switch {
	case height <= 0:
		return 0
	case height == 1:
		return mainnetBlockOneSubsidy
	}

	// Calculate the subsidy by applying the appropriate number of reductions
	// per the requested height.
	reductions := height / mainnetSubsidyReductionInterval
	subsidy := int64(mainnetBaseSubsidy)
	for i := int64(0); i < reductions; i++ {
		subsidy *= mainnetSubsidyReductionMultiplier
		subsidy /= mainnetSubsidyReductionDivisor

		// Stop once no further reduction is possible.  This ensures a bounded
		// computation for large requested intervals and that all future
		// requests for intervals at or after the final reduction interval
		// return 0 without recalculating.
		if subsidy == 0 {
			break
		}
	}
	return subsidy
}

Work (PoW) Proportion Subsidy Calculation

// calcWorkSubsidyDCP0012 returns the proof of work subsidy for a block at the
// provided height and given number of votes using the round 2 modified subsidy
// split.
func calcWorkSubsidyDCP0012(height int64, voters uint16) int64 {
	// These parameters are ordinarily unique per chain and thus should be
	// passed into the function via a chain parameters structure, however,
	// they are defined as constants with the mainnet parameters here for the
	// purposes of providing a self-contained function for the DCP.
	const (
		mainnetStakeValidationHeight = 4096
		votesPerBlock                = 5
		minVotesRequired             = 3 // aka (votesPerBlock / 2) + 1
	)

	// The first block has special subsidy rules.
	if height == 1 {
		return calcBlockSubsidy(height)
	}

	// The subsidy is zero if there are not enough voters once voting begins.  A
	// block without enough voters will fail to validate anyway.
	if height >= mainnetStakeValidationHeight && voters < minVotesRequired {
		return 0
	}

	// Calculate the full block subsidy and reduce it according to the PoW
	// proportion.
	const proportion = 1
	const totalProportions = 100
	subsidy := calcBlockSubsidy(height)
	subsidy *= proportion
	subsidy /= totalProportions

	// Ignore any potential subsidy reductions due to the number of votes prior
	// to the point voting begins.
	if height < mainnetStakeValidationHeight {
		return subsidy
	}

	// Adjust for the number of voters.
	return (int64(voters) * subsidy) / votesPerBlock
}

Stake Vote (PoS) Proportion Subsidy Calculation

// calcStakeVoteSubsidyDCP0012 returns the subsidy for a single stake vote for a
// block at the provided height using the round 2 modified subsidy split.
func calcStakeVoteSubsidyDCP0012(height int64) int64 {
	// These parameters are ordinarily unique per chain and thus should be
	// passed into the function via a chain parameters structure, however,
	// they are defined as constants with the mainnet parameters here for the
	// purposes of providing a self-contained function for the DCP.
	const (
		mainnetStakeValidationHeight = 4096
		votesPerBlock                = 5
	)

	// Votes have no subsidy prior to the point voting begins.  The minus one
	// accounts for the fact that vote subsidies are based on the height that is
	// being voted on as opposed to the block in which they are included.
	if height < mainnetStakeValidationHeight-1 {
		return 0
	}

	// Calculate the full block subsidy and reduce it according to the stake
	// proportion.  Then divide it by the number of votes per block to arrive
	// at the amount per vote.
	const proportion = 89
	const totalProportions = 100
	subsidy := calcBlockSubsidy(height)
	subsidy *= proportion
	subsidy /= (totalProportions * votesPerBlock)

	return subsidy
}

Pull Requests

Subsidy Enforcement

A reference implementation of the required consensus changes to enforce the new subsidy split is provided by pull request #3092.

Deployment

A reference implementation of the required agenda definition is implemented by pull request #3090.

Test Vectors

The following test vectors are provided in order to facilitate testing across implementations. These are the expected values for mainnet.

Subsidy Calculations

All subsidy values are in atoms.

Height Num Votes Full Subsidy Work Subsidy Vote Subsidy Notes
-1 0 0 0 0 negative height, invalid
0 0 0 0 0 genesis block
1 0 168000000000000 168000000000000 0 initial payouts
2 0 3119582664 31195826 0 first non-special block prior voting start
4094 0 3119582664 31195826 0 two blocks prior to voting start
4095 0 3119582664 31195826 555285714 final block prior to voting start
4096 5 3119582664 31195826 555285714 voting start, 5 votes
4096 4 3119582664 24956660 555285714 voting start, 4 votes
4096 3 3119582664 18717495 555285714 voting start, 3 votes
4096 2 3119582664 0 555285714 only 2 votes, invalid block
6143 5 3119582664 31195826 555285714 final block prior to 1st reduction
6144 5 3088695706 30886957 549787835 1st block in 1st reduction, 5 votes
6144 4 3088695706 24709565 549787835 1st block in 1st reduction, 4 votes
12287 5 3088695706 30886957 549787835 last block in 1st reduction
12288 5 3058114560 30581145 544344391 1st block in 2nd reduction
307200 5 1896827356 18968273 337635269 1st block in 50th reduction, 5 votes
307200 3 1896827356 11380963 337635269 1st block in 50th reduction, 3 votes
10401792 5 99 0 17 first zero work subsidy 1693rd reduction
10979328 5 5 0 0 first zero vote subsidy 1787th reduction
11010048 5 0 0 0 first zero full subsidy 1792nd reduction

Acknowledgements

Collaborators

Thanks to the following individuals who provided valuable feedback during the review process of this proposal (alphabetical order):

References

Additional References

  1. Politeia Proposal - Change PoW/PoS Subsidy Split to 1/89 and Change PoW Algorithm to BLAKE3
  2. Politeia Proposal - Change PoW/PoS Subsidy Split From 60/30 to 10/80
  3. The Suppressor Part 1: War of Attrition
  4. The Suppressor Part 2: On-Chain Analysis

Copyright

This document is licensed under the CC0-1.0: Creative Commons CC0 1.0 Universal license.

The code is licensed under the ISC License.