- compare both hash and block num from reward filename to blockchain state

- complete error handling
This commit is contained in:
wanwiset25 2025-04-17 15:39:07 +04:00
parent 4fc208b527
commit 8ca51b6ee4

View file

@ -98,6 +98,7 @@ type TotalRewards struct {
TotalAccountReward *big.Int TotalAccountReward *big.Int
TotalDelegatedReward map[string]*big.Int TotalDelegatedReward map[string]*big.Int
} }
type AccountRewardResponse struct { type AccountRewardResponse struct {
EpochRewards []AccountEpochReward EpochRewards []AccountEpochReward
Total TotalRewards Total TotalRewards
@ -105,6 +106,11 @@ type AccountRewardResponse struct {
type AccountRewardStatus string type AccountRewardStatus string
type rewardFileName struct {
epochBlockNum int
epochBlockHash common.Hash
}
const ( const (
statusMasternode AccountRewardStatus = "MasterNode" statusMasternode AccountRewardStatus = "MasterNode"
statusProtectornode AccountRewardStatus = "ProtectorNode" statusProtectornode AccountRewardStatus = "ProtectorNode"
@ -351,16 +357,21 @@ func calculateSigners(message map[string]SignerTypes, pool map[string]map[common
} }
func (api *API) GetRewardByAccount(account common.Address, begin rpc.BlockNumber, end rpc.BlockNumber) (AccountRewardResponse, error) { func (api *API) GetRewardByAccount(account common.Address, begin rpc.BlockNumber, end rpc.BlockNumber) (AccountRewardResponse, error) {
epochBlocks, err := api.getEpochNumbersFromRewardFiles(&begin, &end) rewardFileNames, err := api.getRewardFileNamesInRange(&begin, &end)
if err != nil { if err != nil {
return AccountRewardResponse{}, err return AccountRewardResponse{}, err
} }
epochRewards := []AccountEpochReward{} epochRewards := []AccountEpochReward{}
for _, epochBlock := range epochBlocks { for _, fileName := range rewardFileNames {
header := api.chain.GetHeaderByNumber(epochBlock) header := api.chain.GetHeaderByHash(fileName.epochBlockHash)
if header == nil { if header == nil {
log.Error("[GetRewardByAccount] header not found, impossible case, please check your RPC", "err", err) // this is the case when there is chain rollback but the reward files of the old chain still remain, skip the reward of unknown blockhash
return AccountRewardResponse{}, err continue
}
if int(header.Number.Int64()) != fileName.epochBlockNum {
log.Error("[GetRewardByAccount] block number mismatch in reward filename", "reward file blocknum", fileName.epochBlockNum, "header blocknum", int(header.Number.Int64()), "blockhash", header.Hash())
return AccountRewardResponse{}, errors.New("reward file block number mismatch")
} }
epochReward, err := getEpochReward(account, header) epochReward, err := getEpochReward(account, header)
if err != nil { if err != nil {
@ -396,7 +407,7 @@ func (api *API) GetRewardByAccount(account common.Address, begin rpc.BlockNumber
return response, nil return response, nil
} }
func (api *API) getEpochNumbersFromRewardFiles(begin, end *rpc.BlockNumber) ([]uint64, error) { func (api *API) getRewardFileNamesInRange(begin, end *rpc.BlockNumber) ([]rewardFileName, error) {
beginHeader := api.getHeaderFromApiBlockNum(begin) beginHeader := api.getHeaderFromApiBlockNum(begin)
if beginHeader == nil { if beginHeader == nil {
return nil, errors.New("illegal begin block number") return nil, errors.New("illegal begin block number")
@ -420,31 +431,43 @@ func (api *API) getEpochNumbersFromRewardFiles(begin, end *rpc.BlockNumber) ([]u
return nil, err return nil, err
} }
var epochNumbers []int var rewardFileNames = []rewardFileName{}
for _, file := range files { for _, file := range files {
if !file.IsDir() { if !file.IsDir() {
filePrefix, _, found := strings.Cut(file.Name(), ".") filePrefix, fileSuffix, found := strings.Cut(file.Name(), ".")
if found { if found {
filePrefixInt, err := strconv.Atoi(filePrefix) filePrefixInt, err := strconv.Atoi(filePrefix)
if err != nil { if err != nil {
log.Warn("[getEpochNumbersFromRewardFiles] found unknown filename format in rewards folder") log.Warn("[getEpochNumbersFromRewardFiles] found unknown filename format in rewards folder")
return nil, err return nil, err
} }
epochNumbers = append(epochNumbers, filePrefixInt) fileSuffixHash := common.StringToHash(fileSuffix)
rewardName := rewardFileName{
epochBlockNum: filePrefixInt,
epochBlockHash: fileSuffixHash,
}
rewardFileNames = append(rewardFileNames, rewardName)
} }
} }
} }
sort.Ints(epochNumbers)
sort.Slice(rewardFileNames, func(i, j int) bool {
return rewardFileNames[i].epochBlockNum < rewardFileNames[j].epochBlockNum
})
epochNumbers := make([]int, len(rewardFileNames))
for i, obj := range rewardFileNames {
epochNumbers[i] = obj.epochBlockNum
}
startIndex := sort.SearchInts(epochNumbers, int(beginHeader.Number.Int64())) startIndex := sort.SearchInts(epochNumbers, int(beginHeader.Number.Int64()))
endIndex := sort.SearchInts(epochNumbers, int(endHeader.Number.Int64())) endIndex := sort.SearchInts(epochNumbers, int(endHeader.Number.Int64()))
var epochNumbersInRange []uint64 var rewardfileNamesInRange []rewardFileName
for i:= startIndex; i<= endIndex; i++{ for i:= startIndex; i<= endIndex; i++{
number := uint64(epochNumbers[i]) rewardfileNamesInRange = append(rewardfileNamesInRange, rewardFileNames[i])
epochNumbersInRange = append(epochNumbersInRange, number)
} }
return rewardfileNamesInRange, nil
return epochNumbersInRange, nil
} }
func getEpochReward(account common.Address, header *types.Header) (AccountEpochReward, error) { func getEpochReward(account common.Address, header *types.Header) (AccountEpochReward, error) {
@ -484,13 +507,17 @@ func (rewardObj *AccountEpochReward) getRewardAndStatus(account string, data map
nodeReward := accountData.(map[string]interface{})["reward"] nodeReward := accountData.(map[string]interface{})["reward"]
delegatedReward := data["rewards"].(map[string]interface{})[account] delegatedReward := data["rewards"].(map[string]interface{})[account]
rewardObj.AccountStatus = statusMasternode rewardObj.AccountStatus = statusMasternode
nodeRewardBigInt, _ := new(big.Int).SetString(nodeReward.(json.Number).String(), 10) nodeRewardBigInt, ok := new(big.Int).SetString(nodeReward.(json.Number).String(), 10)
if ok {
rewardObj.AccountReward = nodeRewardBigInt rewardObj.AccountReward = nodeRewardBigInt
}
for k, v := range delegatedReward.(map[string]interface{}) { for k, v := range delegatedReward.(map[string]interface{}) {
delegatedBigInt, _ := new(big.Int).SetString(v.(json.Number).String(), 10) delegatedBigInt, ok := new(big.Int).SetString(v.(json.Number).String(), 10)
if ok {
rewardObj.DelegatedReward[k] = delegatedBigInt rewardObj.DelegatedReward[k] = delegatedBigInt
} }
}
return return
} }
} }
@ -500,13 +527,17 @@ func (rewardObj *AccountEpochReward) getRewardAndStatus(account string, data map
nodeReward := accountData.(map[string]interface{})["reward"] nodeReward := accountData.(map[string]interface{})["reward"]
delegatedReward := data["rewardsProtector"].(map[string]interface{})[account] delegatedReward := data["rewardsProtector"].(map[string]interface{})[account]
rewardObj.AccountStatus = statusProtectornode rewardObj.AccountStatus = statusProtectornode
nodeRewardBigInt, _ := new(big.Int).SetString(nodeReward.(json.Number).String(), 10) nodeRewardBigInt, successSetNodeReward := new(big.Int).SetString(nodeReward.(json.Number).String(), 10)
if successSetNodeReward {
rewardObj.AccountReward = nodeRewardBigInt rewardObj.AccountReward = nodeRewardBigInt
}
for k, v := range delegatedReward.(map[string]interface{}) { for k, v := range delegatedReward.(map[string]interface{}) {
delegatedBigInt, _ := new(big.Int).SetString(v.(json.Number).String(), 10) delegatedBigInt, successSetDelegatedReward := new(big.Int).SetString(v.(json.Number).String(), 10)
if successSetDelegatedReward {
rewardObj.DelegatedReward[k] = delegatedBigInt rewardObj.DelegatedReward[k] = delegatedBigInt
} }
}
return return
} }
@ -517,13 +548,17 @@ func (rewardObj *AccountEpochReward) getRewardAndStatus(account string, data map
nodeReward := accountData.(map[string]interface{})["reward"] nodeReward := accountData.(map[string]interface{})["reward"]
delegatedReward := data["rewardsObserver"].(map[string]interface{})[account] delegatedReward := data["rewardsObserver"].(map[string]interface{})[account]
rewardObj.AccountStatus = statusObservernode rewardObj.AccountStatus = statusObservernode
nodeRewardBigInt, _ := new(big.Int).SetString(nodeReward.(json.Number).String(), 10) nodeRewardBigInt, successSetNodeReward := new(big.Int).SetString(nodeReward.(json.Number).String(), 10)
if successSetNodeReward {
rewardObj.AccountReward = nodeRewardBigInt rewardObj.AccountReward = nodeRewardBigInt
}
for k, v := range delegatedReward.(map[string]interface{}) { for k, v := range delegatedReward.(map[string]interface{}) {
delegatedBigInt, _ := new(big.Int).SetString(v.(json.Number).String(), 10) delegatedBigInt, successSetDelegatedReward := new(big.Int).SetString(v.(json.Number).String(), 10)
if successSetDelegatedReward {
rewardObj.DelegatedReward[k] = delegatedBigInt rewardObj.DelegatedReward[k] = delegatedBigInt
} }
}
return return
} }
} }