Skip to content
This repository was archived by the owner on Sep 26, 2022. It is now read-only.

Commit 06f0001

Browse files
committed
lnnet - Some code improvements and fixes from @bigspider's review
1 parent 785502a commit 06f0001

File tree

6 files changed

+42
-28
lines changed

6 files changed

+42
-28
lines changed

common/net/bigsize.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def encode(value):
1010
1111
Raises:
1212
:obj:`TypeError`: If the provided value is not an integer.
13-
:obj:`ValueError`: If the provided value is negative or bigger than ``pow(2, 64)``.
13+
:obj:`ValueError`: If the provided value is negative or bigger than ``pow(2, 64) - 1``.
1414
"""
1515

1616
if not isinstance(value, int):
@@ -19,13 +19,13 @@ def encode(value):
1919
if value < 0:
2020
raise ValueError(f"value must be a positive integer, {value} received")
2121

22-
if value < pow(2, 8) - 3:
22+
if value < 253:
2323
return value.to_bytes(1, "big")
2424
elif value < pow(2, 16):
2525
return b"\xfd" + value.to_bytes(2, "big")
2626
elif value < pow(2, 32):
2727
return b"\xfe" + value.to_bytes(4, "big")
28-
elif value <= pow(2, 64):
28+
elif value < pow(2, 64):
2929
return b"\xff" + value.to_bytes(8, "big")
3030
else:
3131
raise ValueError("BigSize can only encode up to 8-byte values")
@@ -49,26 +49,37 @@ def decode(value):
4949
if not isinstance(value, bytes):
5050
raise TypeError(f"value must be bytes, {type(value)} received")
5151

52+
if len(value) == 0:
53+
raise ValueError("Unexpected EOF while decoding BigSize")
54+
5255
if len(value) > 9:
5356
raise ValueError(f"value must be, at most, 9-bytes long, {len(value)} received")
5457

55-
if len(value) > 1:
56-
prefix = value[0]
57-
decoded_value = int.from_bytes(value[1:], "big")
58-
else:
59-
prefix = None
60-
decoded_value = int.from_bytes(value, "big")
58+
if len(value) == 1 and value[0] < 253:
59+
return value[0]
6160

62-
if not prefix and len(value) == 1 and decoded_value < pow(2, 8) - 3:
63-
return decoded_value
64-
elif prefix == 253 and len(value) == 3 and pow(2, 8) - 3 <= decoded_value < pow(2, 16):
65-
return decoded_value
66-
elif prefix == 254 and len(value) == 5 and pow(2, 16) <= decoded_value < pow(2, 32):
67-
return decoded_value
68-
elif prefix == 255 and len(value) == 9 and pow(2, 32) <= decoded_value:
69-
return decoded_value
61+
prefix = value[0]
62+
decoded_value = int.from_bytes(value[1:], "big")
63+
64+
if prefix == 253:
65+
length = 3
66+
min_v = 253
67+
max_v = pow(2, 16)
68+
elif prefix == 254:
69+
length = 5
70+
min_v = pow(2, 16)
71+
max_v = pow(2, 32)
7072
else:
71-
raise ValueError("value is not properly encoded")
73+
length = 9
74+
min_v = pow(2, 32)
75+
max_v = pow(2, 64)
76+
77+
if not len(value) == length:
78+
raise ValueError("Unexpected EOF while decoding BigSize")
79+
elif not min_v <= decoded_value < max_v:
80+
raise ValueError("Encoded BigSize is non-canonical")
81+
else:
82+
return decoded_value
7283

7384

7485
def parse(value):
@@ -93,6 +104,7 @@ def parse(value):
93104

94105
prefix = value[0]
95106

107+
# message length is not explicitly checked here, but wrong length will fail at decode.
96108
if prefix < 253:
97109
# prefix is actually the value to be parsed
98110
return decode(value[0:1]), 1

common/net/bolt1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class PingMessage(Message):
207207

208208
def __init__(self, num_pong_bytes, ignored_bytes=None):
209209
if not 0 <= num_pong_bytes < pow(2, 16):
210-
raise ValueError(f"num_pong_bytes must be between 0 and {pow(2, 16)}")
210+
raise ValueError(f"num_pong_bytes must be between 0 and {pow(2, 16) - 1}")
211211

212212
payload = num_pong_bytes.to_bytes(2, "big")
213213

common/net/bolt9.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,16 @@ def from_bytes(cls, features):
109109

110110
int_features = int.from_bytes(features, "big")
111111
padding = max(2 * len(known_features), int_features.bit_length())
112-
padding = padding + 1 if padding % 2 else padding
112+
padding += padding % 2 # round up to the nearest even number
113113

114114
bit_features = f"{int_features:b}".zfill(padding)
115115
bit_pairs = [bit_features[i : i + 2] for i in range(0, len(bit_features), 2)]
116116
features_dict = {}
117117

118118
for i, pair in enumerate(reversed(bit_pairs)):
119+
if pair == "11":
120+
raise ValueError("Both odd and even bits cannot be set in a pair")
121+
119122
# Known features are stored no matter if they are set or not
120123
odd_bit = 2 * i
121124
feature_name = known_odd_bits.get(odd_bit)
@@ -126,8 +129,7 @@ def from_bytes(cls, features):
126129
features_dict[feature_name] = Feature(odd_bit, is_set=True)
127130
elif pair == "10":
128131
features_dict[feature_name] = Feature(odd_bit + 1, is_set=True)
129-
else:
130-
raise ValueError("Both odd and even bits cannot be set in a pair")
132+
131133
# For unknown features, we only store the ones that are set
132134
else:
133135
feature_name = f"unknown_{odd_bit}"

common/net/tlv.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def __len__(self):
3939
return len(self.serialize())
4040

4141
def __eq__(self, other):
42-
return isinstance(other, TLVRecord) and self.value == other.value
42+
return isinstance(other, TLVRecord) and self.serialize() == other.serialize()
4343

4444
@classmethod
4545
def from_bytes(cls, message):

test/common/unit/net/test_bigsize.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ def test_decode_wrong():
6060

6161
# Wrong encoding
6262
for v in non_canonical:
63-
with pytest.raises(ValueError, match="value is not properly encoded"):
63+
with pytest.raises(ValueError, match="Encoded BigSize is non-canonical"):
6464
bigsize.decode(v)
6565

6666
for v in unexpected_eof:
67-
with pytest.raises(ValueError, match="value is not properly encoded"):
67+
with pytest.raises(ValueError, match="Unexpected EOF while decoding BigSize"):
6868
bigsize.decode(v)
6969

7070

@@ -76,7 +76,7 @@ def test_parse():
7676

7777
# Wrong encoding (behaves exactly like decode_wrong)
7878
for v in non_canonical:
79-
with pytest.raises(ValueError, match="value is not properly encoded"):
79+
with pytest.raises(ValueError, match="Encoded BigSize is non-canonical"):
8080
bigsize.parse(v)
8181

8282

test/common/unit/net/test_bolt1.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,9 @@ def test_ping_message():
268268

269269
def test_ping_message_wrong():
270270
# num_pong_bytes must be an integer between 0 and pow(2, 16)
271-
with pytest.raises(ValueError, match=f"num_pong_bytes must be between 0 and {pow(2, 16)}"):
271+
with pytest.raises(ValueError, match=f"num_pong_bytes must be between 0 and {pow(2, 16) -1}"):
272272
PingMessage(-1)
273-
with pytest.raises(ValueError, match=f"num_pong_bytes must be between 0 and {pow(2, 16)}"):
273+
with pytest.raises(ValueError, match=f"num_pong_bytes must be between 0 and {pow(2, 16) - 1}"):
274274
PingMessage(pow(2, 16))
275275

276276
# ignore_bytes must be bytes if set

0 commit comments

Comments
 (0)