fix earned-reward per key by temporary persisting stats and writing at once (#2693)

sorted slice of map for deterministic write
pull/2695/head
Ganesha Upadhyaya 5 years ago committed by GitHub
parent 9fa85b586b
commit 5b7d2165d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 69
      core/offchain.go

@ -1,7 +1,9 @@
package core package core
import ( import (
"bytes"
"math/big" "math/big"
"sort"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -12,6 +14,7 @@ import (
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/staking/slash" "github.com/harmony-one/harmony/staking/slash"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -214,36 +217,56 @@ func (bc *BlockChain) CommitOffChainData(
); err != nil { ); err != nil {
return NonStatTy, err return NonStatTy, err
} }
tempValidatorStats := map[common.Address]*staking.ValidatorStats{}
for _, paid := range [...][]reward.Payout{ for _, paid := range [...][]reward.Payout{
roundResult.BeaconchainAward, roundResult.ShardChainAward, roundResult.BeaconchainAward, roundResult.ShardChainAward,
} { } {
for i := range paid { for i := range paid {
if stats, err := bc.ReadValidatorStats(paid[i].Addr); err == nil { stats, ok := tempValidatorStats[paid[i].Addr]
doUpdate := false if !ok {
for j := range stats.MetricsPerShard { stats, err = bc.ReadValidatorStats(paid[i].Addr)
if stats.MetricsPerShard[j].Vote.Identity == paid[i].EarningKey { if err != nil {
doUpdate = true utils.Logger().Info().Err(err).
stats.MetricsPerShard[j].Earned.Add( Str("bls-earning-key", paid[i].EarningKey.Hex()).
stats.MetricsPerShard[j].Earned, Msg("could not read validator stats to update for earning per key")
paid[i].NewlyEarned, continue
)
}
} }
if doUpdate { tempValidatorStats[paid[i].Addr] = stats
if err := rawdb.WriteValidatorStats( }
batch, paid[i].Addr, stats, for j := range stats.MetricsPerShard {
); err != nil { if stats.MetricsPerShard[j].Vote.Identity == paid[i].EarningKey {
utils.Logger().Info().Err(err). stats.MetricsPerShard[j].Earned.Add(
Str("bls-earning-key", paid[i].EarningKey.Hex()). stats.MetricsPerShard[j].Earned,
Msg("could not update earning per key in stats") paid[i].NewlyEarned,
} )
} }
} else {
utils.Logger().Info().Err(err).
Str("bls-earning-key", paid[i].EarningKey.Hex()).
Msg("could not read validator stats to update for earning per key")
} }
}
}
type t struct {
addr common.Address
stats *staking.ValidatorStats
}
sortedStats := []t{}
for key, value := range tempValidatorStats {
sortedStats = append(sortedStats, t{key, value})
}
sort.SliceStable(
sortedStats,
func(i, j int) bool {
return bytes.Compare(
sortedStats[i].addr[:], sortedStats[j].addr[:],
) == -1
},
)
for _, stat := range sortedStats {
if err := rawdb.WriteValidatorStats(
batch, stat.addr, stat.stats,
); err != nil {
utils.Logger().Info().Err(err).
Str("validator address", stat.addr.Hex()).
Msg("could not update stats for validator")
} }
} }

Loading…
Cancel
Save