Skip to content

Commit 7aaa541

Browse files
authored
consensus: implement DeepCopy() in PoolObj, close XFN-04 (XinFinOrg#1723)
* add DeepCopy() for PoolObj * PoolObj: use deepcopies and optimize locks * optimize code
1 parent 8451378 commit 7aaa541

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

consensus/XDPoS/utils/pool.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type PoolObj interface {
1010
Hash() common.Hash
1111
PoolKey() string
1212
GetSigner() common.Address
13+
DeepCopy() interface{}
1314
}
1415
type Pool struct {
1516
objList map[string]map[common.Hash]PoolObj
@@ -22,7 +23,17 @@ func NewPool() *Pool {
2223
}
2324
}
2425
func (p *Pool) Get() map[string]map[common.Hash]PoolObj {
25-
return p.objList
26+
p.lock.RLock()
27+
defer p.lock.RUnlock()
28+
dataCopy := make(map[string]map[common.Hash]PoolObj, len(p.objList))
29+
for k1, v1 := range p.objList {
30+
dataCopy[k1] = make(map[common.Hash]PoolObj, len(v1))
31+
for k2, v2 := range v1 {
32+
dataCopy[k1][k2] = v2.DeepCopy().(PoolObj)
33+
}
34+
}
35+
36+
return dataCopy
2637
}
2738

2839
func (p *Pool) Add(obj PoolObj) (int, map[common.Hash]PoolObj) {
@@ -36,10 +47,18 @@ func (p *Pool) Add(obj PoolObj) (int, map[common.Hash]PoolObj) {
3647
}
3748
objListKeyed[obj.Hash()] = obj
3849
numOfItems := len(objListKeyed)
39-
return numOfItems, objListKeyed
50+
51+
dataCopy := make(map[common.Hash]PoolObj, len(objListKeyed))
52+
for k, v := range objListKeyed {
53+
dataCopy[k] = v.DeepCopy().(PoolObj)
54+
}
55+
56+
return numOfItems, dataCopy
4057
}
4158

4259
func (p *Pool) Size(obj PoolObj) int {
60+
p.lock.RLock()
61+
defer p.lock.RUnlock()
4362
poolKey := obj.PoolKey()
4463
objListKeyed, ok := p.objList[poolKey]
4564
if !ok {
@@ -84,8 +103,8 @@ func (p *Pool) Clear() {
84103
}
85104

86105
func (p *Pool) GetObjsByKey(poolKey string) []PoolObj {
87-
p.lock.Lock()
88-
defer p.lock.Unlock()
106+
p.lock.RLock()
107+
defer p.lock.RUnlock()
89108

90109
objListKeyed, ok := p.objList[poolKey]
91110
if !ok {
@@ -94,8 +113,8 @@ func (p *Pool) GetObjsByKey(poolKey string) []PoolObj {
94113
objList := make([]PoolObj, len(objListKeyed))
95114
cnt := 0
96115
for _, obj := range objListKeyed {
97-
objList[cnt] = obj
98-
cnt += 1
116+
objList[cnt] = obj.DeepCopy().(PoolObj)
117+
cnt++
99118
}
100119
return objList
101120
}

core/types/consensus_v2.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import (
1212
type Round uint64
1313
type Signature []byte
1414

15+
func (s Signature) DeepCopy() interface{} {
16+
cpy := make([]byte, len(s))
17+
copy(cpy, s)
18+
return s
19+
}
20+
1521
// Block Info struct in XDPoS 2.0, used for vote message, etc.
1622
type BlockInfo struct {
1723
Hash common.Hash `json:"hash"`
@@ -27,6 +33,20 @@ type Vote struct {
2733
GapNumber uint64 `json:"gapNumber"`
2834
}
2935

36+
func (v *Vote) DeepCopy() interface{} {
37+
proposedBlockInfoCopy := &BlockInfo{
38+
Hash: v.ProposedBlockInfo.Hash,
39+
Round: v.ProposedBlockInfo.Round,
40+
Number: new(big.Int).Set(v.ProposedBlockInfo.Number),
41+
}
42+
return &Vote{
43+
signer: v.signer,
44+
ProposedBlockInfo: proposedBlockInfoCopy,
45+
Signature: v.Signature.DeepCopy().(Signature),
46+
GapNumber: v.GapNumber,
47+
}
48+
}
49+
3050
func (v *Vote) Hash() common.Hash {
3151
return rlpHash(v)
3252
}
@@ -52,6 +72,15 @@ type Timeout struct {
5272
GapNumber uint64
5373
}
5474

75+
func (t *Timeout) DeepCopy() interface{} {
76+
return &Timeout{
77+
signer: t.signer,
78+
Round: t.Round,
79+
Signature: t.Signature.DeepCopy().(Signature),
80+
GapNumber: t.GapNumber,
81+
}
82+
}
83+
5584
func (t *Timeout) Hash() common.Hash {
5685
return rlpHash(t)
5786
}
@@ -75,6 +104,42 @@ type SyncInfo struct {
75104
HighestTimeoutCert *TimeoutCert
76105
}
77106

107+
func (s *SyncInfo) DeepCopy() interface{} {
108+
var highestQCCopy *QuorumCert
109+
if s.HighestQuorumCert != nil {
110+
sigsCopy := make([]Signature, len(s.HighestQuorumCert.Signatures))
111+
for i, sig := range s.HighestQuorumCert.Signatures {
112+
sigsCopy[i] = sig.DeepCopy().(Signature)
113+
}
114+
highestQCCopy = &QuorumCert{
115+
ProposedBlockInfo: &BlockInfo{
116+
Hash: s.HighestQuorumCert.ProposedBlockInfo.Hash,
117+
Round: s.HighestQuorumCert.ProposedBlockInfo.Round,
118+
Number: new(big.Int).Set(s.HighestQuorumCert.ProposedBlockInfo.Number),
119+
},
120+
Signatures: sigsCopy,
121+
GapNumber: s.HighestQuorumCert.GapNumber,
122+
}
123+
}
124+
125+
var highestTimeoutCopy *TimeoutCert
126+
if s.HighestTimeoutCert != nil {
127+
sigsCopy := make([]Signature, len(s.HighestTimeoutCert.Signatures))
128+
for i, sig := range s.HighestTimeoutCert.Signatures {
129+
sigsCopy[i] = sig.DeepCopy().(Signature)
130+
}
131+
highestTimeoutCopy = &TimeoutCert{
132+
Round: s.HighestTimeoutCert.Round,
133+
Signatures: sigsCopy,
134+
GapNumber: s.HighestTimeoutCert.GapNumber,
135+
}
136+
}
137+
return &SyncInfo{
138+
HighestQuorumCert: highestQCCopy,
139+
HighestTimeoutCert: highestTimeoutCopy,
140+
}
141+
}
142+
78143
func (s *SyncInfo) Hash() common.Hash {
79144
return rlpHash(s)
80145
}

0 commit comments

Comments
 (0)