fix(consensus): fix config object not reference to same one and concurrency issues and refactor access pattern (#2146)

* bug fix for using same config object

* update

* change log level to trace on ispochswtich

---------

Co-authored-by: liam.lai <liam.lai@babylonchain.io>
This commit is contained in:
benjamin202410 2026-03-12 12:12:49 -07:00 committed by GitHub
parent c762053cd6
commit be36b32b3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 26 additions and 10 deletions

View file

@ -1,6 +1,7 @@
package engine_v2
import (
"bytes"
"encoding/json"
"errors"
"fmt"
@ -1115,8 +1116,6 @@ func (x *XDPoS_v2) saveRewardToFile(blockHash common.Hash, blockNumber uint64) {
log.Debug("[saveRewardToFile] Saved rewards", "filename", filename)
log.Debug("[saveRewardToFile] Saved rewards", "rewards", string(data))
return
}
func deepCloneJSON(original map[string]interface{}) (map[string]interface{}, error) {
@ -1126,10 +1125,15 @@ func deepCloneJSON(original map[string]interface{}) (map[string]interface{}, err
}
var cloned map[string]interface{}
err = json.Unmarshal(data, &cloned)
if err != nil {
dec := json.NewDecoder(bytes.NewReader(data))
dec.UseNumber()
if err = dec.Decode(&cloned); err != nil {
return nil, fmt.Errorf("failed to unmarshal: %w", err)
}
return cloned, nil
}
func (x *XDPoS_v2) Config(r uint64) *params.V2Config {
return x.config.V2.Config(r)
}

View file

@ -164,7 +164,7 @@ func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
log.Info("[IsEpochSwitch] true, parent equals V2.SwitchBlock", "round", round, "number", header.Number.Uint64(), "hash", header.Hash())
return true, epochNum, nil
}
log.Debug("[IsEpochSwitch]", "is", parentRound < epochStartRound, "parentRound", parentRound, "round", round, "number", header.Number.Uint64(), "epochNum", epochNum, "hash", header.Hash().Hex())
log.Trace("[IsEpochSwitch]", "is", parentRound < epochStartRound, "parentRound", parentRound, "round", round, "number", header.Number.Uint64(), "epochNum", epochNum, "hash", header.Hash().Hex())
// if isEpochSwitch, add to cache
if parentRound < epochStartRound {
x.round2epochBlockInfo.Add(round, &types.BlockInfo{

View file

@ -99,7 +99,8 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
listBlockHash = append(listBlockHash, parentHash)
}
currentConfig := chain.Config().XDPoS.V2.Config(uint64(round))
currentConfig := adaptor.EngineV2.Config(uint64(round))
// add list not miner to penalties
preMasternodes := adaptor.EngineV2.GetMasternodesByHash(chain, currentHash)
penalties := []common.Address{}
@ -286,7 +287,9 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
log.Error("[HookReward] Fail to get round", "error", err)
return nil, err
}
currentConfig := chain.Config().XDPoS.V2.Config(uint64(round))
currentConfig := adaptor.EngineV2.Config(uint64(round))
// Get signers/signing tx count, and burned tokens in one epoch
signers, burnedInOneEpoch, err := GetSigningTxCount(adaptor, chain, header, parentState, currentConfig)

View file

@ -840,11 +840,14 @@ func (v2 *V2) GetCurrentConfig() *V2Config {
}
// avoid CurrentConfig is changed by other goroutines
cpyConfig := *v2.CurrentConfig
return &cpyConfig
cfg := *v2.CurrentConfig
return &cfg
}
func (v2 *V2) Config(round uint64) *V2Config {
v2.lock.RLock()
defer v2.lock.RUnlock()
configRound := round
var index uint64
@ -855,10 +858,16 @@ func (v2 *V2) Config(round uint64) *V2Config {
break
}
}
return v2.AllConfigs[index]
// avoid config is changed by other goroutines
cfg := *v2.AllConfigs[index]
return &cfg
}
func (v2 *V2) BuildConfigIndex() {
v2.lock.Lock()
defer v2.lock.Unlock()
list := slices.Collect(maps.Keys(v2.AllConfigs))
// Make it descending order
slices.SortFunc(list, func(a, b uint64) int {