Skip to content

Commit 2a22f03

Browse files
authored
Merge pull request #129 from solidstate-network/data-structures
Standardize and add new data structures
2 parents b98133f + f0355fb commit 2a22f03

31 files changed

+2939
-31
lines changed

contracts/access/access_control/AccessControlInternal.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
pragma solidity ^0.8.0;
44

5+
import { EnumerableSet } from '../../data/EnumerableSet.sol';
56
import { AddressUtils } from '../../utils/AddressUtils.sol';
6-
import { EnumerableSet } from '../../utils/EnumerableSet.sol';
77
import { UintUtils } from '../../utils/UintUtils.sol';
88
import { IAccessControlInternal } from './IAccessControlInternal.sol';
99
import { AccessControlStorage } from './AccessControlStorage.sol';

contracts/access/access_control/AccessControlStorage.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
pragma solidity ^0.8.0;
44

5-
import { EnumerableSet } from '../../utils/EnumerableSet.sol';
5+
import { EnumerableSet } from '../../data/EnumerableSet.sol';
66

77
library AccessControlStorage {
88
struct RoleData {

contracts/data/BinaryHeap.sol

+335
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.8;
4+
5+
/**
6+
* @title Binary Heap implementation
7+
* @dev The data structure is configured as a max-heap
8+
*/
9+
library BinaryHeap {
10+
struct Heap {
11+
bytes32[] _values;
12+
// 1-indexed to allow 0 to signify nonexistence
13+
mapping(bytes32 => uint256) _indexes;
14+
}
15+
16+
struct Bytes32Heap {
17+
Heap _inner;
18+
}
19+
20+
struct AddressHeap {
21+
Heap _inner;
22+
}
23+
24+
struct UintHeap {
25+
Heap _inner;
26+
}
27+
28+
function at(Bytes32Heap storage heap, uint256 index)
29+
internal
30+
view
31+
returns (bytes32)
32+
{
33+
return _at(heap._inner, index);
34+
}
35+
36+
function at(AddressHeap storage heap, uint256 index)
37+
internal
38+
view
39+
returns (address)
40+
{
41+
return address(uint160(uint256(_at(heap._inner, index))));
42+
}
43+
44+
function at(UintHeap storage heap, uint256 index)
45+
internal
46+
view
47+
returns (uint256)
48+
{
49+
return uint256(_at(heap._inner, index));
50+
}
51+
52+
function contains(Bytes32Heap storage heap, bytes32 value)
53+
internal
54+
view
55+
returns (bool)
56+
{
57+
return _contains(heap._inner, value);
58+
}
59+
60+
function contains(AddressHeap storage heap, address value)
61+
internal
62+
view
63+
returns (bool)
64+
{
65+
return _contains(heap._inner, bytes32(uint256(uint160(value))));
66+
}
67+
68+
function contains(UintHeap storage heap, uint256 value)
69+
internal
70+
view
71+
returns (bool)
72+
{
73+
return _contains(heap._inner, bytes32(value));
74+
}
75+
76+
function indexOf(Bytes32Heap storage heap, bytes32 value)
77+
internal
78+
view
79+
returns (uint256)
80+
{
81+
return _indexOf(heap._inner, value);
82+
}
83+
84+
function indexOf(AddressHeap storage heap, address value)
85+
internal
86+
view
87+
returns (uint256)
88+
{
89+
return _indexOf(heap._inner, bytes32(uint256(uint160(value))));
90+
}
91+
92+
function indexOf(UintHeap storage heap, uint256 value)
93+
internal
94+
view
95+
returns (uint256)
96+
{
97+
return _indexOf(heap._inner, bytes32(value));
98+
}
99+
100+
function length(Bytes32Heap storage heap) internal view returns (uint256) {
101+
return _length(heap._inner);
102+
}
103+
104+
function length(AddressHeap storage heap) internal view returns (uint256) {
105+
return _length(heap._inner);
106+
}
107+
108+
function length(UintHeap storage heap) internal view returns (uint256) {
109+
return _length(heap._inner);
110+
}
111+
112+
function root(Bytes32Heap storage heap) internal view returns (bytes32) {
113+
return _root(heap._inner);
114+
}
115+
116+
function root(AddressHeap storage heap) internal view returns (address) {
117+
return address(uint160(uint256(_root(heap._inner))));
118+
}
119+
120+
function root(UintHeap storage heap) internal view returns (uint256) {
121+
return uint256(_root(heap._inner));
122+
}
123+
124+
function add(Bytes32Heap storage heap, bytes32 value)
125+
internal
126+
returns (bool)
127+
{
128+
return _add(heap._inner, value);
129+
}
130+
131+
function add(AddressHeap storage heap, address value)
132+
internal
133+
returns (bool)
134+
{
135+
return _add(heap._inner, bytes32(uint256(uint160(value))));
136+
}
137+
138+
function add(UintHeap storage heap, uint256 value) internal returns (bool) {
139+
return _add(heap._inner, bytes32(value));
140+
}
141+
142+
function remove(Bytes32Heap storage heap, bytes32 value)
143+
internal
144+
returns (bool)
145+
{
146+
return _remove(heap._inner, value);
147+
}
148+
149+
function remove(AddressHeap storage heap, address value)
150+
internal
151+
returns (bool)
152+
{
153+
return _remove(heap._inner, bytes32(uint256(uint160(value))));
154+
}
155+
156+
function remove(UintHeap storage heap, uint256 value)
157+
internal
158+
returns (bool)
159+
{
160+
return _remove(heap._inner, bytes32(value));
161+
}
162+
163+
function toArray(Bytes32Heap storage heap)
164+
internal
165+
view
166+
returns (bytes32[] memory)
167+
{
168+
uint256 len = _length(heap._inner);
169+
bytes32[] memory arr = new bytes32[](len);
170+
171+
unchecked {
172+
for (uint256 index = 0; index < len; index++) {
173+
arr[index] = at(heap, index);
174+
}
175+
}
176+
177+
return arr;
178+
}
179+
180+
function toArray(AddressHeap storage heap)
181+
internal
182+
view
183+
returns (address[] memory)
184+
{
185+
uint256 len = _length(heap._inner);
186+
address[] memory arr = new address[](len);
187+
188+
unchecked {
189+
for (uint256 index = 0; index < len; index++) {
190+
arr[index] = at(heap, index);
191+
}
192+
}
193+
194+
return arr;
195+
}
196+
197+
function toArray(UintHeap storage heap)
198+
internal
199+
view
200+
returns (uint256[] memory)
201+
{
202+
uint256 len = _length(heap._inner);
203+
uint256[] memory arr = new uint256[](len);
204+
205+
unchecked {
206+
for (uint256 index = 0; index < len; index++) {
207+
arr[index] = at(heap, index);
208+
}
209+
}
210+
211+
return arr;
212+
}
213+
214+
function _at(Heap storage heap, uint256 index)
215+
private
216+
view
217+
returns (bytes32)
218+
{
219+
return heap._values[index];
220+
}
221+
222+
function _contains(Heap storage heap, bytes32 value)
223+
private
224+
view
225+
returns (bool)
226+
{
227+
return heap._indexes[value] != 0;
228+
}
229+
230+
function _indexOf(Heap storage heap, bytes32 value)
231+
private
232+
view
233+
returns (uint256)
234+
{
235+
unchecked {
236+
return heap._indexes[value] - 1;
237+
}
238+
}
239+
240+
function _length(Heap storage heap) private view returns (uint256) {
241+
return heap._values.length;
242+
}
243+
244+
function _root(Heap storage heap) private view returns (bytes32) {
245+
return _at(heap, 0);
246+
}
247+
248+
function _add(Heap storage heap, bytes32 value)
249+
private
250+
returns (bool update)
251+
{
252+
if (!_contains(heap, value)) {
253+
heap._values.push(value);
254+
heap._indexes[value] = _length(heap);
255+
_heapify(heap);
256+
257+
update = true;
258+
}
259+
}
260+
261+
function _remove(Heap storage heap, bytes32 value)
262+
private
263+
returns (bool update)
264+
{
265+
if (_contains(heap, value)) {
266+
uint256 index = _indexOf(heap, value);
267+
268+
unchecked {
269+
// move node with last element in the tree, then remove it
270+
_swap(heap, index, _length(heap) - 1);
271+
}
272+
273+
heap._values.pop();
274+
delete heap._indexes[value];
275+
276+
_heapify(heap);
277+
278+
update = true;
279+
}
280+
}
281+
282+
function _heapify(Heap storage heap) private {
283+
uint256 len = _length(heap);
284+
unchecked {
285+
uint256 index = len / 2;
286+
while (index > 0) {
287+
_maxHeapify(heap, len, --index);
288+
}
289+
}
290+
}
291+
292+
function _maxHeapify(
293+
Heap storage heap,
294+
uint256 len,
295+
uint256 index
296+
) private {
297+
uint256 largest = index;
298+
bytes32[] storage values = heap._values;
299+
300+
unchecked {
301+
uint256 left = (index << 1) | 1;
302+
uint256 right = left + 1;
303+
304+
if (left < len && values[largest] < values[left]) {
305+
largest = left;
306+
}
307+
308+
if (right < len && values[largest] < values[right]) {
309+
largest = right;
310+
}
311+
}
312+
313+
if (largest != index) {
314+
// swap until the largest node is the root node
315+
_swap(heap, index, largest);
316+
_maxHeapify(heap, len, largest);
317+
}
318+
}
319+
320+
function _swap(
321+
Heap storage heap,
322+
uint256 a,
323+
uint256 b
324+
) private {
325+
bytes32[] storage values = heap._values;
326+
327+
bytes32 aValue = values[a];
328+
bytes32 bValue = values[b];
329+
330+
(values[a], values[b]) = (bValue, aValue);
331+
332+
mapping(bytes32 => uint256) storage indexes = heap._indexes;
333+
(indexes[aValue], indexes[bValue]) = (indexes[bValue], indexes[aValue]);
334+
}
335+
}
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.8;
4+
5+
import { BinaryHeap } from './BinaryHeap.sol';
6+
7+
contract BinaryHeapAddressMock {
8+
using BinaryHeap for BinaryHeap.AddressHeap;
9+
10+
BinaryHeap.AddressHeap internal addressHeap;
11+
12+
function at(uint256 index) external view returns (address) {
13+
return addressHeap.at(index);
14+
}
15+
16+
function contains(address value) external view returns (bool) {
17+
return addressHeap.contains(value);
18+
}
19+
20+
function indexOf(address value) external view returns (uint256) {
21+
return addressHeap.indexOf(value);
22+
}
23+
24+
function length() external view returns (uint256) {
25+
return addressHeap.length();
26+
}
27+
28+
function root() external view returns (address) {
29+
return addressHeap.root();
30+
}
31+
32+
function add(address value) external returns (bool) {
33+
return addressHeap.add(value);
34+
}
35+
36+
function remove(address value) external returns (bool) {
37+
return addressHeap.remove(value);
38+
}
39+
40+
function toArray() external view returns (address[] memory) {
41+
return addressHeap.toArray();
42+
}
43+
}

0 commit comments

Comments
 (0)