Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/feature/heartbeats' into heart…
Browse files Browse the repository at this point in the history
…beat
  • Loading branch information
jannotti committed Nov 12, 2024
2 parents 518b65c + fb748a6 commit 67d4f93
Show file tree
Hide file tree
Showing 10 changed files with 522 additions and 193 deletions.
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 @@ -1642,6 +1642,11 @@ func (eval *BlockEvaluator) generateKnockOfflineAccountsList(participating []bas
updates := &eval.block.ParticipationUpdates

ch := FindChallenge(eval.proto.Payouts, current, eval.state, ChActive)
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 @@ -1733,7 +1738,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) ||
ch.Failed(accountAddr, lastSeen) {
updates.AbsentParticipationAccounts = append(
updates.AbsentParticipationAccounts,
Expand Down Expand Up @@ -1770,7 +1780,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 @@ -1911,6 +1921,14 @@ func (eval *BlockEvaluator) validateAbsentOnlineAccounts() error {
addressSet := make(map[basics.Address]bool, suspensionCount)

ch := FindChallenge(eval.proto.Payouts, eval.Round(), eval.state, ChActive)
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 @@ -1931,7 +1949,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 ch.Failed(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

0 comments on commit 67d4f93

Please sign in to comment.