• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CityOfZion / neo3-boa / 0aff654d-b027-49a1-9d97-558d9a2a52ff

05 Mar 2024 04:57PM UTC coverage: 91.985% (-0.1%) from 92.106%
0aff654d-b027-49a1-9d97-558d9a2a52ff

push

circleci

web-flow
Merge pull request #1215 from CityOfZion/CU-86drpndkk

CU-86drpndkk - Refactor test_interop/test_blockchain.py to use BoaTestConstructor

1 of 1 new or added line in 1 file covered. (100.0%)

658 existing lines in 143 files now uncovered.

20635 of 22433 relevant lines covered (91.99%)

1.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.23
/boa3/internal/compiler/codegenerator/vmcodemap.py
1
from boa3.internal.neo.vm.VMCode import VMCode
2✔
2

3

4
class VMCodeMap:
2✔
5
    def __init__(self):
2✔
6
        self._vm_code_list: list[VMCode] = []
2✔
7
        self._vm_code_addresses: list[int] = []
2✔
8

9
        # optimization so it's not needed to iterate over everything in search of targets
10
        self._vm_code_with_target: list[VMCode] = []
2✔
11

12
    def __len__(self) -> int:
2✔
13
        return self._vm_code_list.__len__()
2✔
14

15
    def clear(self):
2✔
16
        self._vm_code_addresses.clear()
2✔
17
        self._vm_code_list.clear()
2✔
18

19
    def get_code_map(self) -> dict[int, VMCode]:
2✔
20
        size = len(self)
2✔
21
        return {self._vm_code_addresses[index]: self._vm_code_list[index] for index in range(size)}
2✔
22

23
    def get_code_list(self) -> list[VMCode]:
2✔
24
        return self._vm_code_list
2✔
25

26
    def get_code_with_target_list(self) -> list[VMCode]:
2✔
27
        return self._vm_code_with_target
2✔
28

29
    def get_bytecode_size(self) -> int:
2✔
30
        if len(self) < 1:
2✔
31
            return 0
2✔
32

33
        return self._vm_code_addresses[-1] + self._vm_code_list[-1].size
2✔
34

35
    def insert_code(self, vm_code: VMCode, has_target: bool = False):
2✔
36
        if vm_code not in self._vm_code_list:
2✔
37
            self._vm_code_addresses.append(self.get_bytecode_size())
2✔
38
            self._vm_code_list.append(vm_code)
2✔
39

40
            if has_target:
2✔
41
                self._vm_code_with_target.append(vm_code)
2✔
42

43
    def get_code(self, address: int) -> VMCode | None:
2✔
44
        try:
2✔
45
            index = self._vm_code_addresses.index(address)
2✔
46
        except ValueError:
2✔
47
            # the address is not int the list
48
            if address >= self.get_bytecode_size():
2✔
49
                # the address is not in the bytecode
50
                return None
2✔
51

52
            # if the address is not the start of a instruction, gets the last instruction before given address
53
            code_address = 0
2✔
54
            for addr in self._vm_code_addresses:
2✔
55
                if addr > address:
2✔
56
                    break
2✔
57
                code_address = addr
2✔
58

59
            index = self._vm_code_addresses.index(code_address)
2✔
60

61
        return self._vm_code_list[index]
2✔
62

63
    def get_start_address(self, vm_code: VMCode) -> int:
2✔
64
        try:
2✔
65
            index = self._vm_code_list.index(vm_code)
2✔
66
            return self._vm_code_addresses[index]
2✔
67
        except ValueError:
2✔
68
            return 0
2✔
69

70
    def get_end_address(self, vm_code: VMCode) -> int:
2✔
71
        try:
2✔
72
            index = self._vm_code_list.index(vm_code) + 1
2✔
73
            if index == len(self._vm_code_list):
2✔
74
                return self.get_bytecode_size()
2✔
75
            else:
76
                return self._vm_code_addresses[index] - 1
2✔
UNCOV
77
        except ValueError:
×
UNCOV
78
            return 0
×
79

80
    def get_addresses(self, start_address: int, end_address: int) -> list[int]:
2✔
81
        if start_address > end_address:
2✔
UNCOV
82
            start_address, end_address = end_address, start_address
×
83

84
        addresses = []
2✔
85
        for address in range(start_address, end_address + 1):
2✔
86
            if address in self._vm_code_addresses:
2✔
87
                addresses.append(address)
2✔
88
        return addresses
2✔
89

90
    def get_addresses_from_codes(self, codes: list[VMCode]) -> list[int]:
2✔
91
        if len(codes) < 1:
2✔
92
            return []
2✔
93

94
        addresses = []
2✔
95
        for vm_code in codes:
2✔
96
            try:
2✔
97
                index = self._vm_code_list.index(vm_code)
2✔
98
                addresses.append(self._vm_code_addresses[index])
2✔
UNCOV
99
            except ValueError:
×
UNCOV
100
                continue
×
101

102
        return addresses
2✔
103

104
    def get_opcodes(self, addresses: list[int]) -> list[VMCode]:
2✔
105
        codes = []
2✔
106

107
        for address in sorted(addresses):
2✔
108
            try:
2✔
109
                index = self._vm_code_addresses.index(address)
2✔
110
                codes.append(self._vm_code_list[index])
2✔
UNCOV
111
            except ValueError:
×
112
                # address not in list
113
                continue
×
114

115
        return codes
2✔
116

117
    def update_addresses(self, start_address: int = 0):
2✔
118
        next_address = -1
2✔
119
        final_size = len(self._vm_code_list)
2✔
120

121
        if len(self._vm_code_addresses) > final_size:
2✔
122
            self._vm_code_addresses = self._vm_code_addresses[:final_size]
2✔
123

124
        for index in range(final_size):
2✔
125
            address = self._vm_code_addresses[index]
2✔
126

127
            if address >= start_address:
2✔
128
                if next_address < 0:
2✔
129
                    if index > 0:
2✔
130
                        new_address = self._vm_code_addresses[index - 1]
2✔
131
                        next_address = new_address + self._vm_code_list[index - 1].size
2✔
132
                    else:
133
                        next_address = 0
2✔
134

135
                if next_address != address:
2✔
136
                    if index < len(self._vm_code_addresses):
2✔
137
                        self._vm_code_addresses[index] = next_address
2✔
138
                    else:
UNCOV
139
                        self._vm_code_addresses.append(next_address)
×
140

141
                next_address += self._vm_code_list[index].size
2✔
142

143
    def move_to_end(self, first_code_address: int, last_code_address: int) -> int | None:
2✔
144
        if last_code_address < first_code_address:
2✔
145
            return
2✔
146

147
        if (len(self._vm_code_addresses) > 0 and
2✔
148
                last_code_address == self._vm_code_addresses[-1]):
149
            # there's nothing to change if it's moving the all the codes
150
            return
2✔
151

152
        first_index = -1
2✔
153
        last_index = 0
2✔
154
        for index, address in enumerate(self._vm_code_addresses):
2✔
155
            if first_code_address <= address and first_index < 0:
2✔
156
                first_index = index
2✔
157
            elif address > last_code_address:
2✔
158
                last_index = index
2✔
159
                break
2✔
160

161
        if first_index >= 0:
2✔
162
            # if the first index was not set, there's nothing to move
163
            if last_index < first_index:
2✔
UNCOV
164
                last_index = len(self._vm_code_addresses)
×
165

166
            self._vm_code_list[first_index:] = (self._vm_code_list[last_index:] +
2✔
167
                                                self._vm_code_list[first_index:last_index])
168
            self.update_addresses(first_code_address)
2✔
169

170
        index = self.get_bytecode_size()
2✔
171
        return index
2✔
172

173
    def remove_opcodes_by_addresses(self, addresses: list[int]):
2✔
174
        was_changed = False
2✔
175
        # reversed so we only need to update addresses once after all are removed
176
        for code_address in sorted(addresses, reverse=True):
2✔
177
            try:
2✔
178
                index = self._vm_code_addresses.index(code_address)
2✔
179
                code = self._vm_code_list.pop(index)
2✔
180

181
                was_changed = True
2✔
182
                self._vm_code_with_target.remove(code)
2✔
183
            except ValueError:
2✔
184
                # don't stop the loop if an address is not found
185
                continue
2✔
186

187
        if was_changed:
2✔
188
            self.update_addresses(min(addresses))
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc