Merge pull request #65 from status-im/ssz-le
ssz: switch to little-endian
This commit is contained in:
commit
55128978ba
|
@ -20,20 +20,20 @@ from milagro_crypto import getRaw, fromRaw
|
||||||
# toBytesSSZ convert simple fixed-length types to their SSZ wire representation
|
# toBytesSSZ convert simple fixed-length types to their SSZ wire representation
|
||||||
func toBytesSSZ(x: SomeInteger): array[sizeof(x), byte] =
|
func toBytesSSZ(x: SomeInteger): array[sizeof(x), byte] =
|
||||||
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
||||||
## All integers are serialized as **big endian**.
|
## All integers are serialized as **little endian**.
|
||||||
|
|
||||||
when x.sizeof == 8: bigEndian64(result.addr, x.unsafeAddr)
|
when x.sizeof == 8: littleEndian64(result.addr, x.unsafeAddr)
|
||||||
elif x.sizeof == 4: bigEndian32(result.addr, x.unsafeAddr)
|
elif x.sizeof == 4: littleEndian32(result.addr, x.unsafeAddr)
|
||||||
elif x.sizeof == 2: bigEndian16(result.addr, x.unsafeAddr)
|
elif x.sizeof == 2: littleEndian16(result.addr, x.unsafeAddr)
|
||||||
elif x.sizeof == 1: copyMem(result.addr, x.unsafeAddr, sizeof(result))
|
elif x.sizeof == 1: copyMem(result.addr, x.unsafeAddr, sizeof(result))
|
||||||
else: {.fatal: "Unsupported type serialization: " & $(type(x)).name.}
|
else: {.fatal: "Unsupported type serialization: " & $(type(x)).name.}
|
||||||
|
|
||||||
func toBytesSSZ(x: Uint24): array[3, byte] =
|
func toBytesSSZ(x: Uint24): array[3, byte] =
|
||||||
## Integers are all encoded as bigendian and not padded
|
## Integers are all encoded as little endian and not padded
|
||||||
let v = x.uint32
|
let v = x.uint32
|
||||||
result[2] = byte(v and 0xff)
|
result[0] = byte(v and 0xff)
|
||||||
result[1] = byte((v shr 8) and 0xff)
|
result[1] = byte((v shr 8) and 0xff)
|
||||||
result[0] = byte((v shr 16) and 0xff)
|
result[2] = byte((v shr 16) and 0xff)
|
||||||
|
|
||||||
func toBytesSSZ(x: bool): array[1, byte] =
|
func toBytesSSZ(x: bool): array[1, byte] =
|
||||||
[if x: 1'u8 else: 0'u8]
|
[if x: 1'u8 else: 0'u8]
|
||||||
|
@ -74,7 +74,7 @@ func sszLen(v: seq | array): int =
|
||||||
# there's enough data in the buffer
|
# there's enough data in the buffer
|
||||||
func fromBytesSSZUnsafe(T: typedesc[SomeInteger], data: pointer): T =
|
func fromBytesSSZUnsafe(T: typedesc[SomeInteger], data: pointer): T =
|
||||||
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
||||||
## All integers are serialized as **big endian**.
|
## All integers are serialized as **little endian**.
|
||||||
## TODO: Assumes data points to a sufficiently large buffer
|
## TODO: Assumes data points to a sufficiently large buffer
|
||||||
|
|
||||||
# TODO: any better way to get a suitably aligned buffer in nim???
|
# TODO: any better way to get a suitably aligned buffer in nim???
|
||||||
|
@ -83,9 +83,9 @@ func fromBytesSSZUnsafe(T: typedesc[SomeInteger], data: pointer): T =
|
||||||
var alignedBuf = cast[ptr byte](tmp.addr)
|
var alignedBuf = cast[ptr byte](tmp.addr)
|
||||||
copyMem(alignedBuf, data, result.sizeof)
|
copyMem(alignedBuf, data, result.sizeof)
|
||||||
|
|
||||||
when result.sizeof == 8: bigEndian64(result.addr, alignedBuf)
|
when result.sizeof == 8: littleEndian64(result.addr, alignedBuf)
|
||||||
elif result.sizeof == 4: bigEndian32(result.addr, alignedBuf)
|
elif result.sizeof == 4: littleEndian32(result.addr, alignedBuf)
|
||||||
elif result.sizeof == 2: bigEndian16(result.addr, alignedBuf)
|
elif result.sizeof == 2: littleEndian16(result.addr, alignedBuf)
|
||||||
elif result.sizeof == 1: copyMem(result.addr, alignedBuf, sizeof(result))
|
elif result.sizeof == 1: copyMem(result.addr, alignedBuf, sizeof(result))
|
||||||
else: {.fatal: "Unsupported type deserialization: " & $(type(result)).name.}
|
else: {.fatal: "Unsupported type deserialization: " & $(type(result)).name.}
|
||||||
|
|
||||||
|
@ -95,12 +95,12 @@ func fromBytesSSZUnsafe(T: typedesc[bool], data: pointer): T =
|
||||||
fromBytesSSZUnsafe(uint8, data) != 0
|
fromBytesSSZUnsafe(uint8, data) != 0
|
||||||
|
|
||||||
func fromBytesSSZUnsafe(T: typedesc[Uint24], data: pointer): T =
|
func fromBytesSSZUnsafe(T: typedesc[Uint24], data: pointer): T =
|
||||||
## Integers are all encoded as bigendian and not padded
|
## Integers are all encoded as littleendian and not padded
|
||||||
var tmp: uint32
|
var tmp: uint32
|
||||||
let p = cast[ptr UncheckedArray[byte]](data)
|
let p = cast[ptr UncheckedArray[byte]](data)
|
||||||
tmp = tmp or uint32(p[2])
|
tmp = tmp or uint32(p[0])
|
||||||
tmp = tmp or uint32(p[1]) shl 8
|
tmp = tmp or uint32(p[1]) shl 8
|
||||||
tmp = tmp or uint32(p[0]) shl 16
|
tmp = tmp or uint32(p[2]) shl 16
|
||||||
result = tmp.Uint24
|
result = tmp.Uint24
|
||||||
|
|
||||||
func fromBytesSSZUnsafe(T: typedesc[EthAddress], data: pointer): T =
|
func fromBytesSSZUnsafe(T: typedesc[EthAddress], data: pointer): T =
|
||||||
|
@ -212,7 +212,7 @@ func serialize[T: not enum](dest: var seq[byte], src: T) =
|
||||||
|
|
||||||
# Write size (we only know it once we've serialized the object!)
|
# Write size (we only know it once we've serialized the object!)
|
||||||
var objLen = dest.len() - lenPos - 4
|
var objLen = dest.len() - lenPos - 4
|
||||||
bigEndian32(dest[lenPos].addr, objLen.addr)
|
littleEndian32(dest[lenPos].addr, objLen.addr)
|
||||||
|
|
||||||
# ################### Core functions ###################################
|
# ################### Core functions ###################################
|
||||||
|
|
||||||
|
@ -262,12 +262,12 @@ func merkleHash[T](lst: openArray[T]): array[32, byte]
|
||||||
|
|
||||||
func hash_tree_root*(x: SomeInteger | bool): array[sizeof(x), byte] =
|
func hash_tree_root*(x: SomeInteger | bool): array[sizeof(x), byte] =
|
||||||
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
||||||
## All integers are serialized as **big endian**.
|
## All integers are serialized as **little endian**.
|
||||||
toBytesSSZ(x)
|
toBytesSSZ(x)
|
||||||
|
|
||||||
func hash_tree_root*(x: Uint24): array[3, byte] =
|
func hash_tree_root*(x: Uint24): array[3, byte] =
|
||||||
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``)
|
||||||
## All integers are serialized as **big endian**.
|
## All integers are serialized as **little endian**.
|
||||||
toBytesSSZ(x)
|
toBytesSSZ(x)
|
||||||
|
|
||||||
func hash_tree_root*(x: EthAddress): array[sizeof(x), byte] =
|
func hash_tree_root*(x: EthAddress): array[sizeof(x), byte] =
|
||||||
|
@ -333,7 +333,7 @@ func merkleHash[T](lst: openArray[T]): array[32, byte] =
|
||||||
# Store length of list (to compensate for non-bijectiveness of padding)
|
# Store length of list (to compensate for non-bijectiveness of padding)
|
||||||
var dataLen: array[32, byte]
|
var dataLen: array[32, byte]
|
||||||
var lstLen = uint64(len(lst))
|
var lstLen = uint64(len(lst))
|
||||||
bigEndian64(dataLen[32-8].addr, lstLen.addr)
|
littleEndian64(dataLen[32-8].addr, lstLen.addr)
|
||||||
|
|
||||||
# Divide into chunks
|
# Divide into chunks
|
||||||
var chunkz: seq[seq[byte]]
|
var chunkz: seq[seq[byte]]
|
||||||
|
|
|
@ -39,14 +39,14 @@ suite "Simple serialization":
|
||||||
)
|
)
|
||||||
|
|
||||||
var expected_ser = @[
|
var expected_ser = @[
|
||||||
byte 0, 0, 0, 67, # length
|
byte 67, 0, 0, 0, # length
|
||||||
5,
|
5,
|
||||||
'\xFF'.ord, '\xFF'.ord, '\xFF'.ord, '\xFD'.ord,
|
0xFD, 0xFF, 0xFF, 0xFF,
|
||||||
]
|
]
|
||||||
expected_ser &= EthAddress.filled(byte 35)
|
expected_ser &= EthAddress.filled(byte 35)
|
||||||
expected_ser &= MDigest[256].filled(byte 35).data
|
expected_ser &= MDigest[256].filled(byte 35).data
|
||||||
expected_ser &= [byte 0, 0, 0, 3, 'c'.ord, 'o'.ord, 'w'.ord]
|
expected_ser &= [byte 3, 0, 0, 0, 'c'.ord, 'o'.ord, 'w'.ord]
|
||||||
expected_ser &= [byte 0, 0, 79]
|
expected_ser &= [byte 79, 0, 0]
|
||||||
|
|
||||||
test "Object deserialization":
|
test "Object deserialization":
|
||||||
let deser = expected_ser.deserialize(Foo).get()
|
let deser = expected_ser.deserialize(Foo).get()
|
||||||
|
@ -119,5 +119,5 @@ suite "Tree hashing":
|
||||||
check: hash_tree_root(bb).len > 0
|
check: hash_tree_root(bb).len > 0
|
||||||
|
|
||||||
test "Hash integer":
|
test "Hash integer":
|
||||||
check: hash_tree_root(0x01'u32) == [0'u8, 0, 0, 1] # big endian!
|
check: hash_tree_root(0x01'u32) == [1'u8, 0, 0, 0] # little endian!
|
||||||
check: hash_tree_root(Uint24(0x01)) == [0'u8, 0, 1] # big endian!
|
check: hash_tree_root(Uint24(0x01)) == [1'u8, 0, 0] # little endian!
|
||||||
|
|
Loading…
Reference in New Issue