Skip to content

Commit 9b2df3f

Browse files
committed
compressed int bug fix + more tests
1 parent 8ee9602 commit 9b2df3f

File tree

3 files changed

+61
-35
lines changed

3 files changed

+61
-35
lines changed

pybtc/functions/tools.py

+36-24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from math import ceil
1+
from math import ceil, floor
22
from io import BytesIO
33
from struct import pack, unpack
44

@@ -167,11 +167,9 @@ def read_var_list(stream, data_type):
167167

168168
# compressed integer
169169

170-
171170
def int_to_c_int(n, base_bytes=1):
172171
"""
173-
Convert integer to compresed integer
174-
172+
Convert integer to compressed integer
175173
:param n: integer.
176174
:param base_bytes: len of bytes base from which start compression.
177175
:return: bytes.
@@ -183,7 +181,15 @@ def int_to_c_int(n, base_bytes=1):
183181
if l <= base_bytes * 8:
184182
return n.to_bytes(base_bytes, byteorder="big")
185183
prefix = 0
186-
payload_bytes = ceil((l)/8) - base_bytes + 1
184+
payload_bytes = ceil((l)/8) - base_bytes
185+
a=payload_bytes
186+
while True:
187+
add_bytes = floor((a) / 8)
188+
a = add_bytes
189+
if add_bytes>=1:
190+
add_bytes+=floor((payload_bytes+add_bytes) / 8) - floor((payload_bytes) / 8)
191+
payload_bytes+=add_bytes
192+
if a==0: break
187193
extra_bytes = int(ceil((l+payload_bytes)/8) - base_bytes)
188194
for i in range(extra_bytes):
189195
prefix += 2 ** i
@@ -193,7 +199,31 @@ def int_to_c_int(n, base_bytes=1):
193199
if prefix.bit_length() % 8:
194200
prefix = prefix << 8 - prefix.bit_length() % 8
195201
n ^= prefix
196-
return n.to_bytes(ceil(n.bit_length()/8), byteorder="big")
202+
return n.to_bytes(ceil(n.bit_length() / 8), byteorder="big")
203+
204+
205+
def c_int_len(n, base_bytes=1):
206+
"""
207+
Get length of compressed integer from integer value
208+
:param n: bytes.
209+
:param base_bytes: len of bytes base from which start compression.
210+
:return: integer.
211+
"""
212+
if n == 0:
213+
return base_bytes
214+
l = n.bit_length() + 1
215+
if l <= base_bytes * 8:
216+
return base_bytes
217+
payload_bytes = ceil((l) / 8) - base_bytes
218+
a = payload_bytes
219+
while True:
220+
add_bytes = floor((a) / 8)
221+
a = add_bytes
222+
if add_bytes >= 1:
223+
add_bytes += floor((payload_bytes + add_bytes) / 8) - floor((payload_bytes) / 8)
224+
payload_bytes += add_bytes
225+
if a == 0: break
226+
return int(ceil((l+payload_bytes)/8))
197227

198228

199229
def c_int_to_int(b, base_bytes=1):
@@ -222,24 +252,6 @@ def c_int_to_int(b, base_bytes=1):
222252
return n
223253

224254

225-
def c_int_len(n, base_bytes=1):
226-
"""
227-
Get length of compressed integer from integer value
228-
229-
:param n: bytes.
230-
:param base_bytes: len of bytes base from which start compression.
231-
:return: integer.
232-
"""
233-
if n == 0:
234-
return base_bytes
235-
l = n.bit_length() + 1
236-
min_bits = base_bytes * 8 - 1
237-
if l <= min_bits + 1:
238-
return base_bytes
239-
payload_bytes = ceil((l)/8) - base_bytes + 1
240-
return int(ceil((l+payload_bytes)/8))
241-
242-
243255
# generic big endian MPI format
244256
def bn_bytes(v, have_ext=False):
245257
ext = 0

pybtc/test/__init__.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
from .hash_functions import *
1+
# from .hash_functions import *
22
from .integer import *
3-
from .address_functions import *
4-
from .script_functions import *
5-
from .ecdsa import *
6-
from .mnemonic import *
7-
from .sighash import *
8-
from .address_class import *
9-
from .transaction_deserialize import *
10-
from .transaction_constructor import *
11-
from .block import *
3+
# from .address_functions import *
4+
# from .script_functions import *
5+
# from .ecdsa import *
6+
# from .mnemonic import *
7+
# from .sighash import *
8+
# from .address_class import *
9+
# from .transaction_deserialize import *
10+
# from .transaction_constructor import *
11+
# from .block import *
1212

1313
# from .script_deserialize import *
1414
# from .create_transaction import *

pybtc/test/integer.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
if parentPath not in sys.path:
55
sys.path.insert(0, parentPath)
66
from pybtc import tools
7-
7+
import math
88

99

1010
def print_bytes(b):
@@ -126,6 +126,20 @@ def test_compressed_integer(self):
126126
for i in range(341616807575530379006368233343265341697 - 10, 341616807575530379006368233343265341697 + 10):
127127
self.assertEqual(tools.c_int_to_int((tools.int_to_c_int(i))), i)
128128
self.assertEqual(tools.c_int_len(i), len(tools.int_to_c_int(i)))
129+
130+
number = 0
131+
old_number = 0
132+
for i in range(0, 1024, 8):
133+
number += 2 ** i
134+
for i in range(old_number, number, int(math.ceil(2 ** i / 20))):
135+
b = 1
136+
a = tools.int_to_c_int(i, b)
137+
c = tools.c_int_to_int(a, b)
138+
l = tools.c_int_len(i)
139+
self.assertEqual(c, i)
140+
self.assertEqual(l, len(a))
141+
old_number = number
142+
129143
def test_variable_integer(self):
130144
for i in range(0, 0xfd):
131145
self.assertEqual(tools.var_int_to_int((tools.int_to_var_int(i))), i)

0 commit comments

Comments
 (0)