chia-blockchain/chia/util/ints.py
Arvid Norberg ca3c8ce407
validate integers in StructStream constructors (#4298)
* validate integers in StructStream constructors

* don't step back sub slots beyond zero

* fix off-by-one in blocks-to-remove

* handle find_fork_point_in_chain() returning -1 in wallet

* fix handling of not finding a shared ancestor in wallet reorg

* terminate clean_block_record() when we reach height 0

* harden int/uint validation in constructor. add comment about int512
2021-06-08 10:45:56 -07:00

80 lines
1.9 KiB
Python

from typing import Any, BinaryIO
from chia.util.struct_stream import StructStream
class int8(StructStream):
PACK = "!b"
class uint8(StructStream):
PACK = "!B"
class int16(StructStream):
PACK = "!h"
class uint16(StructStream):
PACK = "!H"
class int32(StructStream):
PACK = "!l"
class uint32(StructStream):
PACK = "!L"
class int64(StructStream):
PACK = "!q"
class uint64(StructStream):
PACK = "!Q"
class uint128(int):
def __new__(cls: Any, value: int):
value = int(value)
if value > (2 ** 128) - 1 or value < 0:
raise ValueError(f"Value {value} of does not fit into uin128")
return int.__new__(cls, value) # type: ignore
@classmethod
def parse(cls, f: BinaryIO) -> Any:
read_bytes = f.read(16)
assert len(read_bytes) == 16
n = int.from_bytes(read_bytes, "big", signed=False)
assert n <= (2 ** 128) - 1 and n >= 0
return cls(n)
def stream(self, f):
assert self <= (2 ** 128) - 1 and self >= 0
f.write(self.to_bytes(16, "big", signed=False))
class int512(int):
def __new__(cls: Any, value: int):
value = int(value)
# note that the boundaries for int512 is not what you might expect. We
# encode these with one extra byte, but only allow a range of
# [-INT512_MAX, INT512_MAX]
if value >= (2 ** 512) or value <= -(2 ** 512):
raise ValueError(f"Value {value} of does not fit into in512")
return int.__new__(cls, value) # type: ignore
# Uses 65 bytes to fit in the sign bit
@classmethod
def parse(cls, f: BinaryIO) -> Any:
read_bytes = f.read(65)
assert len(read_bytes) == 65
n = int.from_bytes(read_bytes, "big", signed=True)
assert n < (2 ** 512) and n > -(2 ** 512)
return cls(n)
def stream(self, f):
assert self < (2 ** 512) and self > -(2 ** 512)
f.write(self.to_bytes(65, "big", signed=True))