-
Notifications
You must be signed in to change notification settings - Fork 464
/
AccessList.cs
153 lines (122 loc) · 4.84 KB
/
AccessList.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Nethermind.Int256;
namespace Nethermind.Core.Eip2930;
public class AccessList : IEnumerable<(Address Address, AccessList.StorageKeysEnumerable StorageKeys)>
{
private readonly List<(Address address, int count)> _addresses;
private readonly List<UInt256> _keys;
private AccessList(List<(Address address, int count)> addresses, List<UInt256> keys)
{
_addresses = addresses;
_keys = keys;
}
public static AccessList Empty { get; } = new(new List<(Address, int)>(), new List<UInt256>());
public bool IsEmpty => _addresses.Count == 0;
public (int AddressesCount, int StorageKeysCount) Count => (_addresses.Count, _keys.Count);
public class Builder
{
private readonly List<(Address address, int count)> _addresses = new();
private readonly List<UInt256> _keys = new();
private Address? _currentAddress;
public Builder AddAddress(Address address)
{
_addresses.Add((address, 0));
_currentAddress = address;
return this;
}
public Builder AddStorage(in UInt256 index)
{
if (_currentAddress is null)
{
ThrowNoAddress();
}
CollectionsMarshal.AsSpan(_addresses)[^1].count++;
_keys.Add(index);
return this;
[DoesNotReturn]
[StackTraceHidden]
static void ThrowNoAddress()
{
throw new InvalidOperationException("No address known when adding index to the access list");
}
}
public AccessList Build()
{
return new AccessList(_addresses, _keys);
}
}
public Enumerator GetEnumerator() => new(this);
IEnumerator<(Address Address, StorageKeysEnumerable StorageKeys)> IEnumerable<(Address Address, StorageKeysEnumerable StorageKeys)>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public struct Enumerator(AccessList accessList) : IEnumerator<(Address Address, StorageKeysEnumerable StorageKeys)>,
IEnumerator<(Address Address, IEnumerable<UInt256> StorageKeys)>
{
private int _index = -1;
private int _keysIndex = 0;
public bool MoveNext()
{
_index++;
if (_index > 0)
{
_keysIndex += CollectionsMarshal.AsSpan(accessList._addresses)[_index - 1].count;
}
return _index < accessList._addresses.Count;
}
public void Reset()
{
_index = -1;
_keysIndex = 0;
}
public readonly (Address Address, StorageKeysEnumerable StorageKeys) Current
{
get
{
ref readonly var addressCount = ref CollectionsMarshal.AsSpan(accessList._addresses)[_index];
return (addressCount.address, new StorageKeysEnumerable(accessList, _keysIndex, addressCount.count));
}
}
readonly (Address Address, IEnumerable<UInt256> StorageKeys) IEnumerator<(Address Address, IEnumerable<UInt256> StorageKeys)>.Current => Current;
readonly object IEnumerator.Current => Current;
public readonly void Dispose() { }
}
public readonly struct StorageKeysEnumerable : IEnumerable<UInt256>
{
private readonly AccessList _accessList;
private readonly int _index;
private readonly int _count;
public StorageKeysEnumerable(AccessList accessList, int index, int count)
{
_accessList = accessList;
_index = index;
_count = count;
}
StorageKeysEnumerator GetEnumerator() => new(_accessList, _index, _count);
IEnumerator<UInt256> IEnumerable<UInt256>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public struct StorageKeysEnumerator : IEnumerator<UInt256>
{
private readonly AccessList _accessList;
private readonly int _startingIndex;
private readonly int _count;
private int _index = -1;
public StorageKeysEnumerator(AccessList accessList, int index, int count)
{
_accessList = accessList;
_startingIndex = index;
_count = count;
}
public bool MoveNext() => ++_index < _count;
public void Reset() => _index = -1;
public readonly UInt256 Current => _accessList._keys[_startingIndex + _index];
readonly object IEnumerator.Current => Current;
public readonly void Dispose() { }
}
}