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
import (
"bytes"
"math/big"
"sort"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
@ -12,6 +14,7 @@ import (
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/staking/slash"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/pkg/errors"
)
@ -214,36 +217,56 @@ func (bc *BlockChain) CommitOffChainData(
); err != nil {
return NonStatTy, err
}
tempValidatorStats := map[common.Address]*staking.ValidatorStats{}
for _, paid := range [...][]reward.Payout{
roundResult.BeaconchainAward, roundResult.ShardChainAward,
} {
for i := range paid {
if stats, err := bc.ReadValidatorStats(paid[i].Addr); err == nil {
doUpdate := false
for j := range stats.MetricsPerShard {
if stats.MetricsPerShard[j].Vote.Identity == paid[i].EarningKey {
doUpdate = true
stats.MetricsPerShard[j].Earned.Add(
stats.MetricsPerShard[j].Earned,
paid[i].NewlyEarned,
)
}
stats, ok := tempValidatorStats[paid[i].Addr]
if !ok {
stats, err = bc.ReadValidatorStats(paid[i].Addr)
if err != nil {
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")
continue
}
if doUpdate {
if err := rawdb.WriteValidatorStats(
batch, paid[i].Addr, stats,
); err != nil {
utils.Logger().Info().Err(err).
Str("bls-earning-key", paid[i].EarningKey.Hex()).
Msg("could not update earning per key in stats")
}
tempValidatorStats[paid[i].Addr] = stats
}
for j := range stats.MetricsPerShard {
if stats.MetricsPerShard[j].Vote.Identity == paid[i].EarningKey {
stats.MetricsPerShard[j].Earned.Add(
stats.MetricsPerShard[j].Earned,
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