Skip to content

Commit d1fe463

Browse files
committed
[WIP] Implement simple subroutine opcodes
1 parent 89f3fbf commit d1fe463

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

eth/vm/rstack.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from typing import (
2+
List,
3+
)
4+
5+
from eth.exceptions import (
6+
InsufficientStack,
7+
FullStack,
8+
)
9+
10+
from eth.validation import (
11+
validate_stack_int,
12+
)
13+
14+
from eth.utils import (
15+
big_endian_to_int,
16+
ValidationError,
17+
)
18+
19+
20+
"""
21+
This module simply implements for the return stack the exact same design used for the data stack. As this stack must simply push_int or pop1_int any time a subroutine is accessed or left, only those two functions are provided. For the same reason, the class RStack doesn't inherit from the abc StackAPI, as it would require to implement all the abstract methods defined.
22+
"""
23+
24+
class RStack():
25+
"""
26+
VM Return Stack
27+
"""
28+
29+
__slots__ = ['values', '_append', '_pop_int', '__len__']
30+
31+
def __init__(self) -> None:
32+
values: List[int]
33+
self.values = values
34+
self._append = values.append
35+
self._pop_typed = values.pop
36+
self.__len__ = values.__len__
37+
38+
def push_int(self) -> int:
39+
if len(self.values) > 1023:
40+
raise FullStack('Stack limit reached')
41+
42+
validate_stack_int(value)
43+
44+
self._append((int, value))
45+
46+
47+
def pop1_int(self) -> int:
48+
#
49+
# Note: This function is optimized for speed over readability.
50+
#
51+
if not self.values:
52+
raise InsufficientStack("Wanted 1 stack item as int, had none")
53+
else:
54+
item_type, popped = self._pop_typed()
55+
if item_type is int:
56+
return popped # type: ignore
57+
elif item_type is bytes:
58+
return big_endian_to_int(popped) # type: ignore
59+
else:
60+
raise _busted_type(item_type, popped)
61+
62+
def _busted_type(item_type: type, value: Union[int, bytes]) -> ValidationError:
63+
return ValidationError(
64+
"Stack must always be bytes or int, "
65+
f"got {item_type!r} type, val {value!r}"
66+
)
67+
68+

0 commit comments

Comments
 (0)