Skip to content

Commit

Permalink
Do not suspend !IncentiveEligible
Browse files Browse the repository at this point in the history
  • Loading branch information
jannotti committed Dec 9, 2024
1 parent 957364a commit d5286e3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 13 deletions.
21 changes: 13 additions & 8 deletions ledger/eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1632,13 +1632,15 @@ func (eval *BlockEvaluator) proposerPayout() (basics.MicroAlgos, error) {
}

// generateKnockOfflineAccountsList creates the lists of expired or absent
// participation accounts by traversing over the modified accounts in the state
// deltas and testing if any of them needs to be reset/suspended. Expiration
// takes precedence - if an account is expired, it should be knocked offline and
// key material deleted. If it is only suspended, the key material will remain.
// participation accounts to be suspended. It examines the accounts that appear
// in the current block and high-stake accounts being tracked for state
// proofs. Expiration takes precedence - if an account is expired, it should be
// knocked offline and key material deleted. If it is only suspended, the key
// material will remain.
//
// Different ndoes may propose different list of addresses based on node state.
// Block validators only check whether ExpiredParticipationAccounts or
// Different nodes may propose different list of addresses based on node state,
// the protocol does not enforce which accounts must appear. Block validators
// only check whether ExpiredParticipationAccounts or
// AbsentParticipationAccounts meet the criteria for expiration or suspension,
// not whether the lists are complete.
//
Expand Down Expand Up @@ -1740,7 +1742,7 @@ func (eval *BlockEvaluator) generateKnockOfflineAccountsList(participating []bas
updates.ExpiredParticipationAccounts,
accountAddr,
)
continue // if marking expired, do not also suspend
continue // if marking expired, do not consider suspension
}
}

Expand All @@ -1750,7 +1752,7 @@ func (eval *BlockEvaluator) generateKnockOfflineAccountsList(participating []bas
continue // no more room (don't break the loop, since we may have more expiries)
}

if acctData.Status == basics.Online {
if acctData.Status == basics.Online && acctData.IncentiveEligible {
lastSeen := max(acctData.LastProposed, acctData.LastHeartbeat)
oad, lErr := eval.state.lookupAgreement(accountAddr)
if lErr != nil {
Expand Down Expand Up @@ -1882,6 +1884,9 @@ func (eval *BlockEvaluator) validateAbsentOnlineAccounts() error {
if acctData.MicroAlgos.IsZero() {
return fmt.Errorf("proposed absent account %v with zero algos", accountAddr)

Check warning on line 1885 in ledger/eval/eval.go

View check run for this annotation

Codecov / codecov/patch

ledger/eval/eval.go#L1885

Added line #L1885 was not covered by tests
}
if !acctData.IncentiveEligible {
return fmt.Errorf("proposed absent account %v not IncentiveEligible", accountAddr)

Check warning on line 1888 in ledger/eval/eval.go

View check run for this annotation

Codecov / codecov/patch

ledger/eval/eval.go#L1888

Added line #L1888 was not covered by tests
}

oad, lErr := eval.state.lookupAgreement(accountAddr)
if lErr != nil {
Expand Down
21 changes: 16 additions & 5 deletions ledger/eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,7 @@ func TestAbsenteeChecks(t *testing.T) {
crypto.RandBytes(tmp.StateProofID[:])
crypto.RandBytes(tmp.SelectionID[:])
crypto.RandBytes(tmp.VoteID[:])
tmp.IncentiveEligible = true // make suspendable
tmp.VoteFirstValid = 1
tmp.VoteLastValid = 1500 // large enough to avoid EXPIRATION, so we can see SUSPENSION
switch i {
Expand All @@ -1345,16 +1346,25 @@ func TestAbsenteeChecks(t *testing.T) {
tmp.LastProposed = 1 // we want addrs[2] to be suspended earlier than others
case 3:
tmp.LastProposed = 1 // we want addrs[3] to be a proposer, and never suspend itself
case 5:
tmp.LastHeartbeat = 1 // like addr[1] but !IncentiveEligible, no suspend
tmp.IncentiveEligible = false
case 6:
tmp.LastProposed = 1 // like addr[2] but !IncentiveEligible, no suspend
tmp.IncentiveEligible = false
default:
if i < 10 { // make the other 8 genesis wallets unsuspendable
if i%2 == 0 {
if i < 10 { // make 0,3,4,7,8,9 unsuspendable
switch i % 3 {
case 0:
tmp.LastProposed = 1200
} else {
case 1:
tmp.LastHeartbeat = 1200
case 2:
tmp.IncentiveEligible = false
}
} else {
// ensure non-zero balance for new accounts, but a small balance
// so they will not be absent, just challenged.
// ensure non-zero balance for the new accounts, but a small
// balance so they will not be absent, just challenged.
tmp.MicroAlgos = basics.MicroAlgos{Raw: 1_000_000}
tmp.LastHeartbeat = 1 // non-zero allows suspensions
}
Expand Down Expand Up @@ -1385,6 +1395,7 @@ func TestAbsenteeChecks(t *testing.T) {

switch vb.Block().Round() {
case 202: // 2 out of 10 genesis accounts are now absent
require.Len(t, vb.Block().AbsentParticipationAccounts, 2, addrs)
require.Contains(t, vb.Block().AbsentParticipationAccounts, addrs[1])
require.Contains(t, vb.Block().AbsentParticipationAccounts, addrs[2])
case 1000:
Expand Down

0 comments on commit d5286e3

Please sign in to comment.