Skip to content

Commit

Permalink
Incentives: Add fields in block header for proposer and fees collecte…
Browse files Browse the repository at this point in the history
…d. (#617)

* Add fields in block header for proposer and fees collected.
* Add payouts related fields to Account
* update consensus.go
* Add absent participation accounts
  • Loading branch information
jannotti committed Apr 24, 2024
1 parent 3be118b commit 7914b59
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 4 deletions.
122 changes: 118 additions & 4 deletions protocol/config/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,8 @@ type ConsensusParams struct {

EnableExtraPagesOnAppUpdate bool

// MaxProposedExpiredOnlineAccounts is the maximum number of online accounts, which need
// to be taken offline, that would be proposed to be taken offline.
// MaxProposedExpiredOnlineAccounts is the maximum number of online accounts
// that a proposer can take offline for having expired voting keys.
MaxProposedExpiredOnlineAccounts int

// EnableAccountDataResourceSeparation enables the support for extended application and asset storage
Expand Down Expand Up @@ -510,6 +510,101 @@ type ConsensusParams struct {
// arrival times or is set to a static value. Even if this flag disables the
// dynamic filter, it will be calculated and logged (but not used).
DynamicFilterTimeout bool

// Payouts contains parameters for amounts and eligibility for block proposer
// payouts. It excludes information about the "unsustainable" payouts
// described in BonusPlan.
Payouts ProposerPayoutRules

// Bonus contains parameters related to the extra payout made to block
// proposers, unrelated to the fees paid in that block. For it to actually
// occur, extra funds need to be put into the FeeSink. The bonus amount
// decays exponentially.
Bonus BonusPlan
}

// ProposerPayoutRules puts several related consensus parameters in one place. The same
// care for backward compatibility with old blocks must be taken.
type ProposerPayoutRules struct {
// Enabled turns on several things needed for paying block incentives,
// including tracking of the proposer and fees collected.
Enabled bool

// GoOnlineFee imparts a small cost on moving from offline to online. This
// will impose a cost to running unreliable nodes that get suspended and
// then come back online.
GoOnlineFee uint64

// Percent specifies the percent of fees paid in a block that go to the
// proposer instead of the FeeSink.
Percent uint64

// MinBalance is the minimum balance an account must have to be eligible for
// incentives. It ensures that smaller accounts continue to operate for the
// same motivations they had before block incentives were
// introduced. Without that assurance, it is difficult to model their
// behaviour - might many participants join for the hope of easy financial
// rewards, but without caring enough to run a high-quality node?
MinBalance uint64

// MaxBalance is the maximum balance an account can have to be eligible for
// incentives. It encourages large accounts to split their stake to add
// resilience to consensus in the case of outages. Nothing in protocol can
// prevent such accounts from running nodes that share fate (same machine,
// same data center, etc), but this serves as a gentle reminder.
MaxBalance uint64

// MaxMarkAbsent is the maximum number of online accounts, that a proposer
// can suspend for not proposing "lately" (In 10x expected interval, or
// within a grace period from being challenged)
MaxMarkAbsent int

// Challenges occur once every challengeInterval rounds.
ChallengeInterval uint64
// Suspensions happen between 1 and 2 grace periods after a challenge. Must
// be less than half MaxTxnLife to ensure the Block header will be cached
// and less than half ChallengeInterval to avoid overlapping challenges. A larger
// grace period means larger stake nodes will probably propose before they
// need to consider an active heartbeat.
ChallengeGracePeriod uint64
// An account is challenged if the first challengeBits match the start of
// the account address. An online account will be challenged about once
// every interval*2^bits rounds.
ChallengeBits int
}

// BonusPlan describes how the "extra" proposer payouts are to be made. It
// specifies an exponential decay in which the bonus decreases by 1% every n
// rounds. If we need to change the decay rate (only), we would create a new
// plan like:
//
// BaseAmount: 0, DecayInterval: XXX
//
// by using a zero baseAmount, the amount not affected.
// For a bigger change, we'd use a plan like:
//
// BaseRound: <FUTURE round>, BaseAmount: <new amount>, DecayInterval: <new>
//
// or just
//
// BaseAmount: <new amount>, DecayInterval: <new>
//
// the new decay rate would go into effect at upgrade time, and the new
// amount would be set at baseRound or at upgrade time.
type BonusPlan struct {
// BaseRound is the earliest round this plan can apply. Of course, the
// consensus update must also have happened. So using a low value makes it
// go into effect immediately upon upgrade.
BaseRound uint64
// BaseAmount is the bonus to be paid when this plan first applies (see
// baseRound). If it is zero, then no explicit change is made to the bonus
// (useful for only changing the decay rate).
BaseAmount uint64
// DecayInterval is the time in rounds between 1% decays. For simplicity,
// decay occurs based on round % BonusDecayInterval, so a decay can happen right
// after going into effect. The BonusDecayInterval goes into effect at upgrade
// time, regardless of `baseRound`.
DecayInterval uint64
}

// PaysetCommitType enumerates possible ways for the block header to commit to
Expand Down Expand Up @@ -584,10 +679,14 @@ var MaxExtraAppProgramLen int
// supported supported by any of the consensus protocols. used for decoding purposes.
var MaxAvailableAppProgramLen int

// MaxProposedExpiredOnlineAccounts is the maximum number of online accounts, which need
// to be taken offline, that would be proposed to be taken offline.
// MaxProposedExpiredOnlineAccounts is the maximum number of online accounts
// that a proposer can take offline for having expired voting keys.
var MaxProposedExpiredOnlineAccounts int

// MaxMarkAbsent is the maximum number of online accounts that a proposer can
// suspend for not proposing "lately"
var MaxMarkAbsent int

// MaxAppTotalArgLen is the maximum number of bytes across all arguments of an application
// max sum([len(arg) for arg in txn.ApplicationArgs])
var MaxAppTotalArgLen int
Expand Down Expand Up @@ -661,6 +760,7 @@ func checkSetAllocBounds(p ConsensusParams) {
checkSetMax(p.MaxAppProgramLen, &MaxLogCalls)
checkSetMax(p.MaxInnerTransactions*p.MaxTxGroupSize, &MaxInnerTransactionsPerDelta)
checkSetMax(p.MaxProposedExpiredOnlineAccounts, &MaxProposedExpiredOnlineAccounts)
checkSetMax(p.Payouts.MaxMarkAbsent, &MaxMarkAbsent)

// These bounds are exported to make them available to the msgp generator for calculating
// maximum valid message size for each message going across the wire.
Expand Down Expand Up @@ -1323,6 +1423,20 @@ func initConsensusProtocols() {

vFuture.LogicSigVersion = 11 // When moving this to a release, put a new higher LogicSigVersion here

vFuture.Payouts.Enabled = true
vFuture.Payouts.Percent = 75
vFuture.Payouts.GoOnlineFee = 2_000_000 // 2 algos
vFuture.Payouts.MinBalance = 30_000_000_000 // 30,000 algos
vFuture.Payouts.MaxBalance = 70_000_000_000_000 // 70M algos
vFuture.Payouts.MaxMarkAbsent = 32
vFuture.Payouts.ChallengeInterval = 1000
vFuture.Payouts.ChallengeGracePeriod = 200
vFuture.Payouts.ChallengeBits = 5

vFuture.Bonus.BaseAmount = 10_000_000 // 10 Algos
// 2.9 sec rounds gives about 10.8M rounds per year.
vFuture.Bonus.DecayInterval = 250_000 // .99^(10.8/0.25) ~ .648. So 35% decay per year

Consensus[protocol.ConsensusFuture] = vFuture

// vAlphaX versions are an separate series of consensus parameters and versions for alphanet
Expand Down
23 changes: 23 additions & 0 deletions types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ type (
// Genesis hash to which this block belongs.
GenesisHash Digest `codec:"gh"`

// Proposer is the proposer of this block. Like the Seed, agreement adds
// this after the block is assembled by the transaction pool, so that the same block can be prepared
// for multiple participating accounts in the same node. Populated if proto.Payouts.Enabled
Proposer Address `codec:"prp"`

// FeesCollected is the sum of all fees paid by transactions in this
// block. Populated if proto.EnableMining.
FeesCollected MicroAlgos `codec:"fc"`

// Bonus is the bonus incentive to be paid for proposing this block. It
// begins as a consensus parameter value, and decays periodically.
Bonus MicroAlgos `codec:"bi"`

// ProposerPayout is the amount that should be moved from the FeeSink to
// the Proposer at the start of the next block. It is basically the
// bonus + the payouts percent of FeesCollected, but may be zero'd by
// proposer ineligibility.
ProposerPayout MicroAlgos `codec:"pp"`

// Rewards.
//
// When a block is applied, some amount of rewards are accrued to
Expand Down Expand Up @@ -115,6 +134,10 @@ type (
// that needs to be converted to offline since their
// participation key expired.
ExpiredParticipationAccounts []Address `codec:"partupdrmv"`

// AbsentParticipationAccounts contains a list of online accounts that
// needs to be converted to offline since they are not proposing.
AbsentParticipationAccounts []Address `codec:"partupdabs"`
}

// RewardsState represents the global parameters controlling the rate
Expand Down
4 changes: 4 additions & 0 deletions types/statedelta.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ type AccountBaseData struct {
RewardsBase uint64
RewardedMicroAlgos MicroAlgos
AuthAddr Address
IncentiveEligible bool

TotalAppSchema StateSchema // Totals across created globals, and opted in locals.
TotalExtraAppPages uint32 // Total number of extra pages across all created apps
Expand All @@ -168,6 +169,9 @@ type AccountBaseData struct {
TotalAssets uint64 // Total of asset creations and optins (i.e. number of holdings)
TotalBoxes uint64 // Total number of boxes associated to this account
TotalBoxBytes uint64 // Total bytes for this account's boxes. keys _and_ values count

LastProposed Round // The last round that this account proposed the winning block.
LastHeartbeat Round // The last round that this account sent a heartbeat to show it was online.
}

// AccountData provides users of the Balances interface per-account data (like basics.AccountData)
Expand Down

0 comments on commit 7914b59

Please sign in to comment.