Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion agreement/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ func (sel selector) CommitteeSize(proto config.ConsensusParams) uint64 {
// looking at online stake (and status and key material). It is exported so that
// AVM can provide opcodes that return the same data.
func BalanceRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
return r.SubSaturate(basics.Round(2 * cparams.SeedRefreshInterval * cparams.SeedLookback))
return r.SubSaturate(BalanceLookback(cparams))
}

// BalanceLookback is how far back agreement looks when considering balances for
// voting stake.
func BalanceLookback(cparams config.ConsensusParams) basics.Round {
return basics.Round(2 * cparams.SeedRefreshInterval * cparams.SeedLookback)
}

func seedRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
Expand Down
4 changes: 3 additions & 1 deletion ledger/apply/keyreg.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"errors"
"fmt"

"github.com/algorand/go-algorand/agreement"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/transactions"
)
Expand Down Expand Up @@ -79,7 +80,8 @@ func Keyreg(keyreg transactions.KeyregTxnFields, header transactions.Header, bal
}
record.Status = basics.Online
if params.Payouts.Enabled {
record.LastHeartbeat = header.FirstValid
lookback := agreement.BalanceLookback(balances.ConsensusParams())
record.LastHeartbeat = round + lookback
}
record.VoteFirstValid = keyreg.VoteFirst
record.VoteLastValid = keyreg.VoteLast
Expand Down
30 changes: 26 additions & 4 deletions ledger/eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func (x *roundCowBase) onlineStake() (basics.MicroAlgos, error) {
return basics.MicroAlgos{}, err
}
x.totalOnline = total
return x.totalOnline, err
return x.totalOnline, nil
}

func (x *roundCowBase) updateAssetResourceCache(aa ledgercore.AccountAsset, r ledgercore.AssetResource) {
Expand Down Expand Up @@ -1639,6 +1639,11 @@ func (eval *BlockEvaluator) generateKnockOfflineAccountsList(participating []bas
updates := &eval.block.ParticipationUpdates

ch := activeChallenge(&eval.proto, uint64(current), eval.state)
onlineStake, err := eval.state.onlineStake()
if err != nil {
logging.Base().Errorf("unable to fetch online stake, no knockoffs: %v", err)
return
}

// Make a set of candidate addresses to check for expired or absentee status.
type candidateData struct {
Expand Down Expand Up @@ -1730,7 +1735,12 @@ func (eval *BlockEvaluator) generateKnockOfflineAccountsList(participating []bas

if acctData.Status == basics.Online {
lastSeen := max(acctData.LastProposed, acctData.LastHeartbeat)
if isAbsent(eval.state.prevTotals.Online.Money, acctData.MicroAlgosWithRewards, lastSeen, current) ||
oad, lErr := eval.state.lookupAgreement(accountAddr)
if lErr != nil {
logging.Base().Errorf("unable to check account for absenteeism: %v", accountAddr)
continue
}
if isAbsent(onlineStake, oad.VotingStake(), lastSeen, current) ||
failsChallenge(ch, accountAddr, lastSeen) {
updates.AbsentParticipationAccounts = append(
updates.AbsentParticipationAccounts,
Expand Down Expand Up @@ -1767,7 +1777,7 @@ func isAbsent(totalOnlineStake basics.MicroAlgos, acctStake basics.MicroAlgos, l
// 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 {
if lastSeen == 0 || acctStake.Raw == 0 {
return false
}
// See if the account has exceeded 10x their expected observation interval.
Expand Down Expand Up @@ -1881,6 +1891,14 @@ func (eval *BlockEvaluator) validateAbsentOnlineAccounts() error {
addressSet := make(map[basics.Address]bool, suspensionCount)

ch := activeChallenge(&eval.proto, uint64(eval.Round()), eval.state)
totalOnlineStake, err := eval.state.onlineStake()
if err != nil {
logging.Base().Errorf("unable to fetch online stake, can't check knockoffs: %v", err)
// I suppose we can still return successfully if the absent list is empty.
if len(eval.block.ParticipationUpdates.AbsentParticipationAccounts) > 0 {
return err
}
}

for _, accountAddr := range eval.block.ParticipationUpdates.AbsentParticipationAccounts {
if _, exists := addressSet[accountAddr]; exists {
Expand All @@ -1901,7 +1919,11 @@ func (eval *BlockEvaluator) validateAbsentOnlineAccounts() error {
}

lastSeen := max(acctData.LastProposed, acctData.LastHeartbeat)
if isAbsent(eval.state.prevTotals.Online.Money, acctData.MicroAlgos, lastSeen, eval.Round()) {
oad, lErr := eval.state.lookupAgreement(accountAddr)
if lErr != nil {
return fmt.Errorf("unable to check absent account: %v", accountAddr)
}
if isAbsent(totalOnlineStake, oad.VotingStake(), lastSeen, eval.Round()) {
continue // ok. it's "normal absent"
}
if failsChallenge(ch, accountAddr, lastSeen) {
Expand Down
11 changes: 9 additions & 2 deletions ledger/eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -804,9 +804,16 @@ func (ledger *evalTestLedger) GetKnockOfflineCandidates(rnd basics.Round, _ conf
return ret, nil
}

// OnlineCirculation just returns a deterministic value for a given round.
// OnlineCirculation add up the balances of all online accounts in rnd. It
// doesn't remove expired accounts.
func (ledger *evalTestLedger) OnlineCirculation(rnd, voteRound basics.Round) (basics.MicroAlgos, error) {
return basics.MicroAlgos{Raw: uint64(rnd) * 1_000_000}, nil
circulation := basics.MicroAlgos{}
for _, data := range ledger.roundBalances[rnd] {
if data.Status == basics.Online {
circulation.Raw += data.MicroAlgos.Raw
}
}
return circulation, nil
}

func (ledger *evalTestLedger) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
Expand Down
Loading