Coverage for comm/utils.py: 57%
69 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 20:41 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 20:41 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2021 RSK Labs Ltd
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy of
6# this software and associated documentation files (the "Software"), to deal in
7# the Software without restriction, including without limitation the rights to
8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9# of the Software, and to permit persons to whom the Software is furnished to do
10# so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
23import re
26def bitwise_and_bytes(bs1, bs2):
27 return bytes(x & y for (x, y) in zip(bs1, bs2))
30def assert_int(obj, key):
31 _assert_key_present(obj, key)
32 if type(obj[key]) != int:
33 raise ValueError("%s is not an integer" % _name_from_key(key))
36def assert_bool(obj, key):
37 _assert_key_present(obj, key)
38 if type(obj[key]) != bool:
39 raise ValueError("%s is not a boolean value" % _name_from_key(key))
42def assert_dict(obj, key):
43 _assert_key_present(obj, key)
44 if type(obj[key]) != dict:
45 raise ValueError("%s is not an object" % _name_from_key(key))
48def assert_hex_hash(obj, key):
49 _assert_key_present(obj, key)
50 if not is_hex_string_of_length(obj[key], 32):
51 raise ValueError(
52 "%s is not a hexadecimal value representing a block hash"
53 % _name_from_key(key)
54 )
57def _assert_keys_present(obj, keys):
58 for key in keys:
59 _assert_key_present(obj, key)
62def _assert_key_present(obj, key):
63 if key not in obj:
64 raise ValueError("%s not present" % _name_from_key(key))
67def _name_from_key(key):
68 name = key.split("_")
69 name[0] = name[0].capitalize()
70 name = " ".join(name)
71 return name
74def is_hex_string_of_length(value, num_bytes, allow_prefix=False):
75 try:
76 if allow_prefix and value.startswith("0x"):
77 value = value[2:]
78 bs = bytes.fromhex(value)
80 return len(bs) == num_bytes
81 except Exception:
82 return False
85def is_nonempty_hex_string(value):
86 try:
87 bs = bytes.fromhex(value)
88 return len(bs) > 0
89 except Exception:
90 return False
93def hex_or_decimal_string_to_int(value):
94 if value.startswith("0x"):
95 return int(value, 16)
97 return int(value, 10)
100def normalize_hex_string(value):
101 if value.startswith("0x"):
102 return value[2:]
104 return value
107def has_nonempty_hex_field(mp, name):
108 return name in mp and \
109 type(mp[name]) == str and \
110 is_nonempty_hex_string(mp[name])
113def has_hex_field_of_length(mp, name, length):
114 return name in mp and \
115 type(mp[name]) == str and \
116 is_hex_string_of_length(mp[name], length)
119def has_field_of_type(mp, name, tp):
120 return name in mp and \
121 type(mp[name]) == tp
124# Utility functions to parse and use a list slice
125# from a string (in the python fashion [nn:mm])
126_SLICE_REGEXP = re.compile("^(-?\\d*):(-?\\d*)$", re.ASCII)
129def is_slice_str(s):
130 return _SLICE_REGEXP.match(s) is not None
133def slice_from_str(s):
134 m = _SLICE_REGEXP.match(s)
136 if m is None:
137 raise ValueError(f'Invalid slice str "{s}"')
139 gs = m.groups()
140 start = 0 if gs[0] == "" else int(gs[0])
141 stop = None if gs[1] == "" else int(gs[1])
143 return slice(start, stop, 1)