@@ -45,6 +45,12 @@ type binaryIterator struct {
45
45
// accounts in a slow, but easily verifiable way. Note this function is used
46
46
// for initialization, use `newBinaryAccountIterator` as the API.
47
47
func (dl * diskLayer ) initBinaryAccountIterator (seek common.Hash ) * binaryIterator {
48
+ // The state set in the disk layer is mutable, hold the lock before obtaining
49
+ // the account list to prevent concurrent map iteration and write.
50
+ dl .lock .RLock ()
51
+ accountList := dl .buffer .states .accountList ()
52
+ dl .lock .RUnlock ()
53
+
48
54
// Create two iterators for state buffer and the persistent state in disk
49
55
// respectively and combine them as a binary iterator.
50
56
l := & binaryIterator {
@@ -54,7 +60,7 @@ func (dl *diskLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator
54
60
// The account key list for iteration is deterministic once the iterator
55
61
// is constructed, no matter the referenced disk layer is stale or not
56
62
// later.
57
- a : newDiffAccountIterator (seek , dl . buffer . states , nil ),
63
+ a : newDiffAccountIterator (seek , accountList , nil ),
58
64
b : newDiskAccountIterator (dl .db .diskdb , seek ),
59
65
}
60
66
l .aDone = ! l .a .Next ()
@@ -68,28 +74,34 @@ func (dl *diskLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator
68
74
func (dl * diffLayer ) initBinaryAccountIterator (seek common.Hash ) * binaryIterator {
69
75
parent , ok := dl .parent .(* diffLayer )
70
76
if ! ok {
77
+ // The state set in diff layer is immutable and will never be stale,
78
+ // so the read lock protection is unnecessary.
79
+ accountList := dl .states .stateSet .accountList ()
71
80
l := & binaryIterator {
72
81
// The account loader function is unnecessary; the account key list
73
82
// produced by the supplied state set alone is sufficient for iteration.
74
83
//
75
84
// The account key list for iteration is deterministic once the iterator
76
85
// is constructed, no matter the referenced disk layer is stale or not
77
86
// later.
78
- a : newDiffAccountIterator (seek , dl . states . stateSet , nil ),
87
+ a : newDiffAccountIterator (seek , accountList , nil ),
79
88
b : dl .parent .(* diskLayer ).initBinaryAccountIterator (seek ),
80
89
}
81
90
l .aDone = ! l .a .Next ()
82
91
l .bDone = ! l .b .Next ()
83
92
return l
84
93
}
94
+ // The state set in diff layer is immutable and will never be stale,
95
+ // so the read lock protection is unnecessary.
96
+ accountList := dl .states .stateSet .accountList ()
85
97
l := & binaryIterator {
86
98
// The account loader function is unnecessary; the account key list
87
99
// produced by the supplied state set alone is sufficient for iteration.
88
100
//
89
101
// The account key list for iteration is deterministic once the iterator
90
102
// is constructed, no matter the referenced disk layer is stale or not
91
103
// later.
92
- a : newDiffAccountIterator (seek , dl . states . stateSet , nil ),
104
+ a : newDiffAccountIterator (seek , accountList , nil ),
93
105
b : parent .initBinaryAccountIterator (seek ),
94
106
}
95
107
l .aDone = ! l .a .Next ()
@@ -101,6 +113,12 @@ func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator
101
113
// storage slots in a slow, but easily verifiable way. Note this function is used
102
114
// for initialization, use `newBinaryStorageIterator` as the API.
103
115
func (dl * diskLayer ) initBinaryStorageIterator (account common.Hash , seek common.Hash ) * binaryIterator {
116
+ // The state set in the disk layer is mutable, hold the lock before obtaining
117
+ // the storage list to prevent concurrent map iteration and write.
118
+ dl .lock .RLock ()
119
+ storageList := dl .buffer .states .storageList (account )
120
+ dl .lock .RUnlock ()
121
+
104
122
// Create two iterators for state buffer and the persistent state in disk
105
123
// respectively and combine them as a binary iterator.
106
124
l := & binaryIterator {
@@ -110,7 +128,7 @@ func (dl *diskLayer) initBinaryStorageIterator(account common.Hash, seek common.
110
128
// The storage key list for iteration is deterministic once the iterator
111
129
// is constructed, no matter the referenced disk layer is stale or not
112
130
// later.
113
- a : newDiffStorageIterator (account , seek , dl . buffer . states , nil ),
131
+ a : newDiffStorageIterator (account , seek , storageList , nil ),
114
132
b : newDiskStorageIterator (dl .db .diskdb , account , seek ),
115
133
}
116
134
l .aDone = ! l .a .Next ()
@@ -124,28 +142,34 @@ func (dl *diskLayer) initBinaryStorageIterator(account common.Hash, seek common.
124
142
func (dl * diffLayer ) initBinaryStorageIterator (account common.Hash , seek common.Hash ) * binaryIterator {
125
143
parent , ok := dl .parent .(* diffLayer )
126
144
if ! ok {
145
+ // The state set in diff layer is immutable and will never be stale,
146
+ // so the read lock protection is unnecessary.
147
+ storageList := dl .states .stateSet .storageList (account )
127
148
l := & binaryIterator {
128
149
// The storage loader function is unnecessary; the storage key list
129
150
// produced by the supplied state set alone is sufficient for iteration.
130
151
//
131
152
// The storage key list for iteration is deterministic once the iterator
132
153
// is constructed, no matter the referenced disk layer is stale or not
133
154
// later.
134
- a : newDiffStorageIterator (account , seek , dl . states . stateSet , nil ),
155
+ a : newDiffStorageIterator (account , seek , storageList , nil ),
135
156
b : dl .parent .(* diskLayer ).initBinaryStorageIterator (account , seek ),
136
157
}
137
158
l .aDone = ! l .a .Next ()
138
159
l .bDone = ! l .b .Next ()
139
160
return l
140
161
}
162
+ // The state set in diff layer is immutable and will never be stale,
163
+ // so the read lock protection is unnecessary.
164
+ storageList := dl .states .stateSet .storageList (account )
141
165
l := & binaryIterator {
142
166
// The storage loader function is unnecessary; the storage key list
143
167
// produced by the supplied state set alone is sufficient for iteration.
144
168
//
145
169
// The storage key list for iteration is deterministic once the iterator
146
170
// is constructed, no matter the referenced disk layer is stale or not
147
171
// later.
148
- a : newDiffStorageIterator (account , seek , dl . states . stateSet , nil ),
172
+ a : newDiffStorageIterator (account , seek , storageList , nil ),
149
173
b : parent .initBinaryStorageIterator (account , seek ),
150
174
}
151
175
l .aDone = ! l .a .Next ()
0 commit comments