Skip to content

Commit ba2806e

Browse files
authored
Merge pull request #1140 from carver/simpler-sequence-builder
Simplify sequence_builder
2 parents 8e437eb + 2b396fa commit ba2806e

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

tests/trinity/core/header-utils/test_block_number_sequence_builder.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import pytest
22

33
from eth.constants import UINT_256_MAX
4+
5+
from trinity.exceptions import OversizeObject
46
from trinity.utils.headers import sequence_builder
57

68

@@ -22,7 +24,22 @@
2224
(9, 5, 1, True, (9, 7, 5, 3, 1)),
2325
(1, 9, 0, True, (1, 0)),
2426
(UINT_256_MAX - 1, 4, 0, False, (UINT_256_MAX - 1, UINT_256_MAX, )),
27+
# can handle mildly large numbers
28+
(400000000, 1000000, 0, False, tuple(range(400000000, 401000000))),
2529
),
2630
)
2731
def test_sequence(start_num, max_length, skip, reverse, expected):
2832
assert sequence_builder(start_num, max_length, skip, reverse) == expected
33+
34+
35+
TOO_LONG = 2000000
36+
37+
38+
@pytest.mark.parametrize('reverse', (True, False))
39+
@pytest.mark.parametrize('start_num', (0, 400000000))
40+
@pytest.mark.parametrize('skip', (0, 10000))
41+
def test_oversize_sequence(start_num, skip, reverse):
42+
# Instead of using the specific constant, just use a rough TOO_LONG number
43+
# We don't need to worry about edge cases for this gut check
44+
with pytest.raises(OversizeObject):
45+
sequence_builder(start_num, TOO_LONG, skip, reverse)

trinity/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
SYNC_FULL = 'full'
22
SYNC_LIGHT = 'light'
3+
4+
MAXIMUM_OBJECT_MEMORY_BYTES = 10000000

trinity/exceptions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,10 @@ class SyncRequestAlreadyProcessed(BaseTrinityError):
3737
Raised when a trie SyncRequest has already been processed.
3838
"""
3939
pass
40+
41+
42+
class OversizeObject(BaseTrinityError):
43+
"""
44+
Raised when an object is bigger than comfortably fits in memory.
45+
"""
46+
pass

trinity/utils/headers.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
from typing import (
2-
Iterator,
2+
Tuple,
33
)
44

5-
from eth_utils import to_tuple
6-
75
from eth.constants import UINT_256_MAX
86

7+
from trinity.constants import MAXIMUM_OBJECT_MEMORY_BYTES
8+
from trinity.exceptions import OversizeObject
9+
910

10-
@to_tuple
1111
def sequence_builder(start_number: int,
1212
max_length: int,
1313
skip: int,
14-
reverse: bool) -> Iterator[int]:
14+
reverse: bool) -> Tuple[int, ...]:
15+
# Limit the in-memory size of this sequence.
16+
# A tuple of 64-bit ints is about 8 bytes per value
17+
# Ignore the cutoffs at 0 and UINT_256_MAX, because this is just a gut check anyway,
18+
# we should never be approaching this value.
19+
if max_length > MAXIMUM_OBJECT_MEMORY_BYTES // 8:
20+
raise OversizeObject("Sequence is too big to fit in memory: {}".format(max_length))
21+
1522
if reverse:
1623
step = -1 * (skip + 1)
1724
else:
1825
step = skip + 1
1926

2027
cutoff_number = start_number + step * max_length
2128

22-
for number in range(start_number, cutoff_number, step):
23-
if number < 0 or number > UINT_256_MAX:
24-
return
25-
else:
26-
yield number
29+
whole_range = range(start_number, cutoff_number, step)
30+
31+
return tuple(number for number in whole_range if 0 <= number <= UINT_256_MAX)

0 commit comments

Comments
 (0)