From f3a0622e5a42f82283a85761fb53c39e261cd4da Mon Sep 17 00:00:00 2001 From: wanwiset25 Date: Sun, 2 Nov 2025 04:31:38 +0400 Subject: [PATCH 1/3] add DeepCopy() for PoolObj --- consensus/XDPoS/utils/pool.go | 1 + core/types/consensus_v2.go | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/consensus/XDPoS/utils/pool.go b/consensus/XDPoS/utils/pool.go index 9c09a8ba53bd..d7b43944f953 100644 --- a/consensus/XDPoS/utils/pool.go +++ b/consensus/XDPoS/utils/pool.go @@ -10,6 +10,7 @@ type PoolObj interface { Hash() common.Hash PoolKey() string GetSigner() common.Address + DeepCopy() interface{} } type Pool struct { objList map[string]map[common.Hash]PoolObj diff --git a/core/types/consensus_v2.go b/core/types/consensus_v2.go index 2f573ca3543e..78d192b4475b 100644 --- a/core/types/consensus_v2.go +++ b/core/types/consensus_v2.go @@ -27,6 +27,20 @@ type Vote struct { GapNumber uint64 `json:"gapNumber"` } +func (v *Vote) DeepCopy() interface{} { + proposedBlockInfoCopy := &BlockInfo{ + Hash: v.ProposedBlockInfo.Hash, + Round: v.ProposedBlockInfo.Round, + Number: new(big.Int).Set(v.ProposedBlockInfo.Number), + } + return &Vote{ + signer: v.signer, + ProposedBlockInfo: proposedBlockInfoCopy, + Signature: append([]byte(nil), v.Signature...), + GapNumber: v.GapNumber, + } +} + func (v *Vote) Hash() common.Hash { return rlpHash(v) } @@ -52,6 +66,15 @@ type Timeout struct { GapNumber uint64 } +func (t *Timeout) DeepCopy() interface{} { + return &Timeout{ + signer: t.signer, + Round: t.Round, + Signature: append([]byte(nil), t.Signature...), + GapNumber: t.GapNumber, + } +} + func (t *Timeout) Hash() common.Hash { return rlpHash(t) } @@ -75,6 +98,42 @@ type SyncInfo struct { HighestTimeoutCert *TimeoutCert } +func (s *SyncInfo) DeepCopy() interface{} { + var highestQCCopy *QuorumCert + if s.HighestQuorumCert != nil { + sigsCopy := make([]Signature, len(s.HighestQuorumCert.Signatures)) + for i, sig := range s.HighestQuorumCert.Signatures { + sigsCopy[i] = append([]byte(nil), sig...) + } + highestQCCopy = &QuorumCert{ + ProposedBlockInfo: &BlockInfo{ + Hash: s.HighestQuorumCert.ProposedBlockInfo.Hash, + Round: s.HighestQuorumCert.ProposedBlockInfo.Round, + Number: new(big.Int).Set(s.HighestQuorumCert.ProposedBlockInfo.Number), + }, + Signatures: sigsCopy, + GapNumber: s.HighestQuorumCert.GapNumber, + } + } + + var highestTimeoutCopy *TimeoutCert + if s.HighestTimeoutCert != nil { + sigsCopy := make([]Signature, len(s.HighestTimeoutCert.Signatures)) + for i, sig := range s.HighestTimeoutCert.Signatures { + sigsCopy[i] = append([]byte(nil), sig...) + } + highestTimeoutCopy = &TimeoutCert{ + Round: s.HighestTimeoutCert.Round, + Signatures: sigsCopy, + GapNumber: s.HighestTimeoutCert.GapNumber, + } + } + return &SyncInfo{ + HighestQuorumCert: highestQCCopy, + HighestTimeoutCert: highestTimeoutCopy, + } +} + func (s *SyncInfo) Hash() common.Hash { return rlpHash(s) } From 815f327942573624bb759e39f8bcecd1e151ce3a Mon Sep 17 00:00:00 2001 From: wanwiset25 Date: Sun, 2 Nov 2025 04:56:40 +0400 Subject: [PATCH 2/3] PoolObj: use deepcopies and optimize locks --- consensus/XDPoS/utils/pool.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/consensus/XDPoS/utils/pool.go b/consensus/XDPoS/utils/pool.go index d7b43944f953..8d977d6bba4b 100644 --- a/consensus/XDPoS/utils/pool.go +++ b/consensus/XDPoS/utils/pool.go @@ -1,6 +1,7 @@ package utils import ( + "maps" "sync" "github.com/XinFinOrg/XDPoSChain/common" @@ -23,7 +24,17 @@ func NewPool() *Pool { } } func (p *Pool) Get() map[string]map[common.Hash]PoolObj { - return p.objList + p.lock.RLock() + defer p.lock.RUnlock() + dataCopy := maps.Clone(p.objList) + for k, v := range dataCopy { + dataCopy[k] = make(map[common.Hash]PoolObj, len(dataCopy[k])) + for k2, v2 := range v { + dataCopy[k][k2] = v2.DeepCopy().(PoolObj) + } + } + + return dataCopy } func (p *Pool) Add(obj PoolObj) (int, map[common.Hash]PoolObj) { @@ -37,10 +48,18 @@ func (p *Pool) Add(obj PoolObj) (int, map[common.Hash]PoolObj) { } objListKeyed[obj.Hash()] = obj numOfItems := len(objListKeyed) - return numOfItems, objListKeyed + + dataCopy := maps.Clone(objListKeyed) + for k, v := range dataCopy { + dataCopy[k] = v.DeepCopy().(PoolObj) + } + + return numOfItems, dataCopy } func (p *Pool) Size(obj PoolObj) int { + p.lock.RLock() + defer p.lock.RUnlock() poolKey := obj.PoolKey() objListKeyed, ok := p.objList[poolKey] if !ok { @@ -85,8 +104,8 @@ func (p *Pool) Clear() { } func (p *Pool) GetObjsByKey(poolKey string) []PoolObj { - p.lock.Lock() - defer p.lock.Unlock() + p.lock.RLock() + defer p.lock.RUnlock() objListKeyed, ok := p.objList[poolKey] if !ok { @@ -95,7 +114,7 @@ func (p *Pool) GetObjsByKey(poolKey string) []PoolObj { objList := make([]PoolObj, len(objListKeyed)) cnt := 0 for _, obj := range objListKeyed { - objList[cnt] = obj + objList[cnt] = obj.DeepCopy().(PoolObj) cnt += 1 } return objList From f572b7d9e24e8fd20c42747589ee14eff1bb0de9 Mon Sep 17 00:00:00 2001 From: wanwiset25 Date: Sun, 2 Nov 2025 22:39:25 +0400 Subject: [PATCH 3/3] optimize code --- consensus/XDPoS/utils/pool.go | 17 ++++++++--------- core/types/consensus_v2.go | 14 ++++++++++---- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/consensus/XDPoS/utils/pool.go b/consensus/XDPoS/utils/pool.go index 8d977d6bba4b..c2d177a06834 100644 --- a/consensus/XDPoS/utils/pool.go +++ b/consensus/XDPoS/utils/pool.go @@ -1,7 +1,6 @@ package utils import ( - "maps" "sync" "github.com/XinFinOrg/XDPoSChain/common" @@ -26,11 +25,11 @@ func NewPool() *Pool { func (p *Pool) Get() map[string]map[common.Hash]PoolObj { p.lock.RLock() defer p.lock.RUnlock() - dataCopy := maps.Clone(p.objList) - for k, v := range dataCopy { - dataCopy[k] = make(map[common.Hash]PoolObj, len(dataCopy[k])) - for k2, v2 := range v { - dataCopy[k][k2] = v2.DeepCopy().(PoolObj) + dataCopy := make(map[string]map[common.Hash]PoolObj, len(p.objList)) + for k1, v1 := range p.objList { + dataCopy[k1] = make(map[common.Hash]PoolObj, len(v1)) + for k2, v2 := range v1 { + dataCopy[k1][k2] = v2.DeepCopy().(PoolObj) } } @@ -49,8 +48,8 @@ func (p *Pool) Add(obj PoolObj) (int, map[common.Hash]PoolObj) { objListKeyed[obj.Hash()] = obj numOfItems := len(objListKeyed) - dataCopy := maps.Clone(objListKeyed) - for k, v := range dataCopy { + dataCopy := make(map[common.Hash]PoolObj, len(objListKeyed)) + for k, v := range objListKeyed { dataCopy[k] = v.DeepCopy().(PoolObj) } @@ -115,7 +114,7 @@ func (p *Pool) GetObjsByKey(poolKey string) []PoolObj { cnt := 0 for _, obj := range objListKeyed { objList[cnt] = obj.DeepCopy().(PoolObj) - cnt += 1 + cnt++ } return objList } diff --git a/core/types/consensus_v2.go b/core/types/consensus_v2.go index 78d192b4475b..12f35c9b1744 100644 --- a/core/types/consensus_v2.go +++ b/core/types/consensus_v2.go @@ -12,6 +12,12 @@ import ( type Round uint64 type Signature []byte +func (s Signature) DeepCopy() interface{} { + cpy := make([]byte, len(s)) + copy(cpy, s) + return s +} + // Block Info struct in XDPoS 2.0, used for vote message, etc. type BlockInfo struct { Hash common.Hash `json:"hash"` @@ -36,7 +42,7 @@ func (v *Vote) DeepCopy() interface{} { return &Vote{ signer: v.signer, ProposedBlockInfo: proposedBlockInfoCopy, - Signature: append([]byte(nil), v.Signature...), + Signature: v.Signature.DeepCopy().(Signature), GapNumber: v.GapNumber, } } @@ -70,7 +76,7 @@ func (t *Timeout) DeepCopy() interface{} { return &Timeout{ signer: t.signer, Round: t.Round, - Signature: append([]byte(nil), t.Signature...), + Signature: t.Signature.DeepCopy().(Signature), GapNumber: t.GapNumber, } } @@ -103,7 +109,7 @@ func (s *SyncInfo) DeepCopy() interface{} { if s.HighestQuorumCert != nil { sigsCopy := make([]Signature, len(s.HighestQuorumCert.Signatures)) for i, sig := range s.HighestQuorumCert.Signatures { - sigsCopy[i] = append([]byte(nil), sig...) + sigsCopy[i] = sig.DeepCopy().(Signature) } highestQCCopy = &QuorumCert{ ProposedBlockInfo: &BlockInfo{ @@ -120,7 +126,7 @@ func (s *SyncInfo) DeepCopy() interface{} { if s.HighestTimeoutCert != nil { sigsCopy := make([]Signature, len(s.HighestTimeoutCert.Signatures)) for i, sig := range s.HighestTimeoutCert.Signatures { - sigsCopy[i] = append([]byte(nil), sig...) + sigsCopy[i] = sig.DeepCopy().(Signature) } highestTimeoutCopy = &TimeoutCert{ Round: s.HighestTimeoutCert.Round,