COnsistent IO API between fromRawUint and fromHex and add fromUint

This commit is contained in:
Mamy André-Ratsimbazafy 2020-02-09 15:38:30 +01:00
parent 1d92ab1f48
commit b9a37825a3
No known key found for this signature in database
GPG Key ID: 7B88AD1FE79492E1
2 changed files with 24 additions and 17 deletions

View File

@ -20,9 +20,9 @@ import
#
# ############################################################
func parseRawUintLE(
src: openarray[byte],
bits: static int): BigInt[bits] {.inline.}=
func fromRawUintLE(
T: type BigInt,
src: openarray[byte]): T =
## Parse an unsigned integer from its canonical
## little-endian unsigned representation
## And store it into a BigInt of size bits
@ -52,22 +52,29 @@ func parseRawUintLE(
if acc_len != 0:
result.limbs[dst_idx] = acc
func parseRawUint*(
func fromRawUint*(
T: type BigInt,
src: openarray[byte],
bits: static int,
srcEndianness: static Endianness): BigInt[bits] =
srcEndianness: static Endianness): T {.inline.}=
## Parse an unsigned integer from its canonical
## big-endian or little-endian unsigned representation
## And store it into a BigInt of size bits
## And store it into a BigInt of size `bits`
##
## CT:
## - no leaks
when srcEndianness == littleEndian:
parseRawUintLE(src, bits)
fromRawUintLE(T, src)
else:
{.error: "Not implemented at the moment".}
func fromUint*(
T: type BigInt,
src: SomeUnsignedInt): T =
## Parse a regular unsigned integer
## and store it into a BigInt of size `bits`
fromRawUint(T, cast[array[sizeof(src), byte]](src), cpuEndian)
# ############################################################
#
# Serialising from internal representation to canonical format
@ -291,7 +298,7 @@ func fromHex*(T: type BigInt, s: string): T =
hexToPaddedByteArray(s, bytes, littleEndian)
# 2. Convert canonical uint to Big Int
result = parseRawUint(bytes, T.bits, littleEndian)
result = T.fromRawUint(bytes, littleEndian)
func dumpHex*(big: BigInt, order: static Endianness = bigEndian): string =
## Stringify an int to hex.

View File

@ -17,7 +17,7 @@ suite "IO":
block: # Sanity check
let x = 0'u64
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, cpuEndian)
let big = BigInt[64].fromRawUint(x_bytes, cpuEndian)
check:
T(big.limbs[0]) == 0
@ -26,7 +26,7 @@ suite "IO":
block: # 2^63 is properly represented on 2 limbs
let x = 1'u64 shl 63
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, cpuEndian)
let big = BigInt[64].fromRawUint(x_bytes, cpuEndian)
check:
T(big.limbs[0]) == 0
@ -37,7 +37,7 @@ suite "IO":
# "Little-endian" - 2^63
let x = 1'u64 shl 63
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
let big = BigInt[64].fromRawUint(x_bytes, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
var r_bytes: array[8, byte]
dumpRawUint(r_bytes, big, littleEndian)
@ -46,7 +46,7 @@ suite "IO":
block: # "Little-endian" - single random
let x = uint64 rand(0..high(int))
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
let big = BigInt[64].fromRawUint(x_bytes, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
var r_bytes: array[8, byte]
dumpRawUint(r_bytes, big, littleEndian)
@ -56,7 +56,7 @@ suite "IO":
for _ in 0 ..< 10:
let x = uint64 rand(0..high(int))
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
let big = BigInt[64].fromRawUint(x_bytes, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
var r_bytes: array[8, byte]
dumpRawUint(r_bytes, big, littleEndian)
@ -65,21 +65,21 @@ suite "IO":
test "Round trip on elliptic curve constants":
block: # Secp256k1 - https://en.bitcoin.it/wiki/Secp256k1
const p = "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"
let x = fromHex(BigInt[256], p)
let x = BigInt[256].fromHex(p)
let hex = x.dumpHex(bigEndian)
check: p == hex
block: # BN254 - https://github.com/ethereum/py_ecc/blob/master/py_ecc/fields/field_properties.py
const p = "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
let x = fromHex(BigInt[254], p)
let x = BigInt[254].fromHex(p)
let hex = x.dumpHex(bigEndian)
check: p == hex
block: # BLS12-381 - https://github.com/ethereum/py_ecc/blob/master/py_ecc/fields/field_properties.py
const p = "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
let x = fromHex(BigInt[381], p)
let x = BigInt[381].fromHex(p)
let hex = x.dumpHex(bigEndian)
check: p == hex