Skip to content

Commit

Permalink
Make the absenteeism factor = 20 instead of 10
Browse files Browse the repository at this point in the history
  • Loading branch information
jannotti committed Dec 4, 2024
1 parent d2954e5 commit 8bc1e0d
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 25 deletions.
4 changes: 2 additions & 2 deletions ledger/apply/heartbeat.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ func Heartbeat(hb transactions.HeartbeatTxnFields, header transactions.Header, b
kind = "cheap"
}

// These first checks are a little draconian. The idea is not let these
// free transactions do anything except their exact intended purpose.
// These first checks are a little draconian. Don't let these free
// transactions do anything except their exact intended purpose.
if len(header.Note) > 0 {
return fmt.Errorf("%s heartbeat is not allowed to have a note", kind)
}
Expand Down
11 changes: 7 additions & 4 deletions ledger/eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1768,18 +1768,21 @@ func (eval *BlockEvaluator) generateKnockOfflineAccountsList(participating []bas
}
}

const absentFactor = 20

func isAbsent(totalOnlineStake basics.MicroAlgos, acctStake basics.MicroAlgos, lastSeen basics.Round, current basics.Round) bool {
// Don't consider accounts that were online when payouts went into effect as
// absent. They get noticed the next time they propose or keyreg, which
// ought to be soon, if they are high stake or want to earn incentives.
if lastSeen == 0 || acctStake.Raw == 0 {
return false
}
// See if the account has exceeded 10x their expected observation interval.
allowableLag, o := basics.Muldiv(10, totalOnlineStake.Raw, acctStake.Raw)
// See if the account has exceeded their expected observation interval.
allowableLag, o := basics.Muldiv(absentFactor, totalOnlineStake.Raw, acctStake.Raw)
if o {
// This can't happen with 10B total possible stake, but if we imagine
// another algorand network with huge possible stake, this seems reasonable.
// This can't happen with 10B total possible stake and a reasonable
// absentFactor, but if we imagine another algorand network with huge
// possible stake, this seems reasonable.
allowableLag = math.MaxInt64 / acctStake.Raw
}
return lastSeen+basics.Round(allowableLag) < current
Expand Down
18 changes: 9 additions & 9 deletions ledger/eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ func TestAbsenteeChecks(t *testing.T) {
blkEval = l.nextBlock(t)

switch vb.Block().Round() {
case 102: // 2 out of 10 genesis accounts are now absent
case 202: // 2 out of 10 genesis accounts are now absent
require.Contains(t, vb.Block().AbsentParticipationAccounts, addrs[1])
require.Contains(t, vb.Block().AbsentParticipationAccounts, addrs[2])
case 1000:
Expand Down Expand Up @@ -1613,13 +1613,13 @@ func TestIsAbsent(t *testing.T) {
var absent = func(total uint64, acct uint64, last uint64, current uint64) bool {
return isAbsent(basics.Algos(total), basics.Algos(acct), basics.Round(last), basics.Round(current))
}
// 1% of stake, absent for 1000 rounds
a.False(absent(1000, 10, 5000, 6000))
a.True(absent(1000, 10, 5000, 6001)) // longer
a.True(absent(1000, 11, 5000, 6001)) // more acct stake
a.False(absent(1000, 9, 5000, 6001)) // less acct stake
a.False(absent(1001, 10, 5000, 6001)) // more online stake
a.False(absent(1000, 10, 5000, 6000)) // 1% of stake, absent for 1000 rounds
a.False(absent(1000, 10, 5000, 7000)) // 1% of stake, absent for 2000 rounds
a.True(absent(1000, 10, 5000, 7001)) // 2001
a.True(absent(1000, 11, 5000, 7000)) // more acct stake drives percent down, makes it absent
a.False(absent(1000, 9, 5000, 7001)) // less acct stake
a.False(absent(1001, 10, 5000, 7001)) // more online stake
// not absent if never seen
a.False(absent(1000, 10, 0, 6000))
a.False(absent(1000, 10, 0, 6001))
a.False(absent(1000, 10, 0, 2001))
a.True(absent(1000, 10, 1, 2002))
}
14 changes: 8 additions & 6 deletions ledger/eval_simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,9 @@ func TestAbsentTracking(t *testing.T) {

var addr1off basics.Round
var addr2off basics.Round
// We're at 20, skip ahead by lookback + 30 to see the knockoffs
// We're at 20, skip ahead by lookback + 60 to see the knockoffs
const absentFactor = 20
skip := basics.Round(3) * absentFactor
for {
vb := dl.fullBlock()
printAbsent(vb)
Expand Down Expand Up @@ -643,12 +645,12 @@ func TestAbsentTracking(t *testing.T) {
checkState(addrs[2], true, true, 833_333_331_429_333) // after keyreg w/ 2A is effective
}

if rnd > 20+lookback+30 {
if rnd > 20+lookback+skip {
break
}
}
require.Equal(t, addr2Eligible+lookback+30, addr2off)
require.Equal(t, addr1Keyreg+lookback+31, addr1off) // addr1 paid out a little bit, extending its lag by 1
require.Equal(t, addr2Eligible+lookback+skip, addr2off)
require.Equal(t, addr1Keyreg+lookback+skip+1, addr1off) // addr1 paid out a little bit, extending its lag by 1

require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[0]).Status) // genesis account
require.Equal(t, basics.Offline, lookup(t, dl.generator, addrs[1]).Status)
Expand Down Expand Up @@ -683,11 +685,11 @@ func TestAbsentTracking(t *testing.T) {
addr2check = true
}

if rnd > 20+2*lookback+30 {
if rnd > 20+2*lookback+skip {
break
}
}
// sanity check that we didn't skip one because of checkstate advanacing a round
// sanity check that we didn't skip one because of checkstate advancing a round
require.True(t, addr1check)
require.True(t, addr2check)

Expand Down
7 changes: 3 additions & 4 deletions test/e2e-go/features/incentives/suspension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ func TestBasicSuspension(t *testing.T) {
// Start a three-node network (70,20,10), all online
// Wait for 10 and 20% nodes to propose (we never suspend accounts with lastProposed=lastHeartbeat=0)
// Stop them both
// Run for 55 rounds, which is enough for 20% node to be suspended, but not 10%
// Run for 105 rounds, which is enough for 20% node to be suspended, but not 10%
// check neither suspended, send a tx from 20% to 10%, only 20% gets suspended
// TODO once we have heartbeats: bring them back up, make sure 20% gets back online
const suspend20 = 55
// bring n20 back up, make sure it gets back online by proposing during the lookback
const suspend20 = 105 // 1.00/0.20 * absentFactor

var fixture fixtures.RestClientFixture
// Speed up rounds. Long enough lookback, so 20% node has a chance to
Expand Down Expand Up @@ -101,7 +101,6 @@ func TestBasicSuspension(t *testing.T) {
a.NotZero(account.VoteID)
a.False(account.IncentiveEligible) // suspension turns off flag

// TODO: n10 wasn't turned off, it's still online
account, err = c10.AccountData(account10.Address)
a.NoError(err)
a.Equal(basics.Online, account.Status)
Expand Down

0 comments on commit 8bc1e0d

Please sign in to comment.