mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-20 22:38:11 +00:00
Merge pull request #1267 from ethereum/dankrad-patch-9
Define Bitlist/Bitvector serialization using bytes, not bigints
This commit is contained in:
commit
77f007cab5
@ -118,8 +118,10 @@ return b""
|
||||
### `Bitvector[N]`
|
||||
|
||||
```python
|
||||
as_integer = sum([value[i] << i for i in range(len(value))])
|
||||
return as_integer.to_bytes((N + 7) // 8, "little")
|
||||
array = [0] * ((N + 7) // 8)
|
||||
for i in range(N):
|
||||
array[i // 8] |= value[i] << (i % 8)
|
||||
return bytes(array)
|
||||
```
|
||||
|
||||
### `Bitlist[N]`
|
||||
@ -127,8 +129,11 @@ return as_integer.to_bytes((N + 7) // 8, "little")
|
||||
Note that from the offset coding, the length (in bytes) of the bitlist is known. An additional leading `1` bit is added so that the length in bits will also be known.
|
||||
|
||||
```python
|
||||
as_integer = (1 << len(value)) + sum([value[i] << i for i in range(len(value))])
|
||||
return as_integer.to_bytes((as_integer.bit_length() + 7) // 8, "little")
|
||||
array = [0] * ((len(value) // 8) + 1)
|
||||
for i in range(len(value)):
|
||||
array[i // 8] |= value[i] << (i % 8)
|
||||
array[len(value) // 8] |= 1 << (len(value) % 8)
|
||||
return bytes(array)
|
||||
```
|
||||
|
||||
### Vectors, containers, lists, unions
|
||||
|
@ -41,11 +41,14 @@ def serialize(obj: SSZValue):
|
||||
if isinstance(obj, BasicValue):
|
||||
return serialize_basic(obj)
|
||||
elif isinstance(obj, Bitvector):
|
||||
as_integer = sum([obj[i] << i for i in range(len(obj))])
|
||||
return as_integer.to_bytes((len(obj) + 7) // 8, "little")
|
||||
return obj.as_bytes()
|
||||
elif isinstance(obj, Bitlist):
|
||||
as_integer = (1 << len(obj)) + sum([obj[i] << i for i in range(len(obj))])
|
||||
return as_integer.to_bytes((as_integer.bit_length() + 7) // 8, "little")
|
||||
as_bytearray = list(obj.as_bytes())
|
||||
if len(obj) % 8 == 0:
|
||||
as_bytearray.append(1)
|
||||
else:
|
||||
as_bytearray[len(obj) // 8] |= 1 << (len(obj) % 8)
|
||||
return bytes(as_bytearray)
|
||||
elif isinstance(obj, Series):
|
||||
return encode_series(obj)
|
||||
else:
|
||||
@ -92,12 +95,10 @@ def encode_series(values: Series):
|
||||
def pack(values: Series):
|
||||
if isinstance(values, bytes): # Bytes and BytesN are already packed
|
||||
return values
|
||||
elif isinstance(values, Bitvector):
|
||||
as_integer = sum([values[i] << i for i in range(len(values))])
|
||||
return as_integer.to_bytes((values.length + 7) // 8, "little")
|
||||
elif isinstance(values, Bitlist):
|
||||
as_integer = sum([values[i] << i for i in range(len(values))])
|
||||
return as_integer.to_bytes((values.length + 7) // 8, "little")
|
||||
elif isinstance(values, Bits):
|
||||
# packs the bits in bytes, left-aligned.
|
||||
# Exclusive length delimiting bits for bitlists.
|
||||
return values.as_bytes()
|
||||
return b''.join([serialize_basic(value) for value in values])
|
||||
|
||||
|
||||
|
@ -354,7 +354,12 @@ class BitElementsType(ElementsType):
|
||||
|
||||
|
||||
class Bits(BaseList, metaclass=BitElementsType):
|
||||
pass
|
||||
|
||||
def as_bytes(self):
|
||||
as_bytearray = [0] * ((len(self) + 7) // 8)
|
||||
for i in range(len(self)):
|
||||
as_bytearray[i // 8] |= int(self[i]) << (i % 8)
|
||||
return bytes(as_bytearray)
|
||||
|
||||
|
||||
class Bitlist(Bits):
|
||||
|
Loading…
x
Reference in New Issue
Block a user