diff --git a/constantine.nimble b/constantine.nimble index 01e20b6..0b7efc4 100644 --- a/constantine.nimble +++ b/constantine.nimble @@ -20,4 +20,4 @@ task test, "Run all tests": test "", "tests/test_io.nim" test "", "tests/test_bigints.nim" test "", "tests/test_bigints_multimod.nim" - test " -d:testingCurves", "tests/test_field_fp.nim" + # test " -d:testingCurves", "tests/test_field_fp.nim" diff --git a/tests/test_bigints.nim b/tests/test_bigints.nim index f77b844..cef30df 100644 --- a/tests/test_bigints.nim +++ b/tests/test_bigints.nim @@ -12,194 +12,197 @@ import unittest, random, strutils, ../constantine/config/common, ../constantine/primitives/constant_time -suite "isZero": - test "isZero for zero": - var x: BigInt[128] - check: x.isZero().bool - test "isZero for non-zero": - block: - var x = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - check: not x.isZero().bool - block: - var x = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") - check: not x.isZero().bool - block: - var x = fromHex(BigInt[128], "0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF") - check: not x.isZero().bool +proc main() = + suite "isZero": + test "isZero for zero": + var x: BigInt[128] + check: x.isZero().bool + test "isZero for non-zero": + block: + var x = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + check: not x.isZero().bool + block: + var x = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") + check: not x.isZero().bool + block: + var x = fromHex(BigInt[128], "0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF") + check: not x.isZero().bool -suite "Arithmetic operations - Addition": - test "Adding 2 zeros": - var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") - let carry = a.add(b, ctrue(Word)) - check: a.isZero().bool - - test "Adding 1 zero - real addition": - block: + suite "Arithmetic operations - Addition": + test "Adding 2 zeros": var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let carry = a.add(b, ctrue(Word)) - - let c = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - check: - bool(a == c) - block: - var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") let carry = a.add(b, ctrue(Word)) + check: a.isZero().bool - let c = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - check: - bool(a == c) + test "Adding 1 zero - real addition": + block: + var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let carry = a.add(b, ctrue(Word)) - test "Adding 1 zero - fake addition": - block: - var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let carry = a.add(b, cfalse(Word)) + let c = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + check: + bool(a == c) + block: + var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") + let carry = a.add(b, ctrue(Word)) - let c = a - check: - bool(a == c) - block: - var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") - let carry = a.add(b, cfalse(Word)) + let c = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + check: + bool(a == c) - let c = a - check: - bool(a == c) + test "Adding 1 zero - fake addition": + block: + var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let carry = a.add(b, cfalse(Word)) - test "Adding non-zeros - real addition": - block: - var a = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let carry = a.add(b, ctrue(Word)) + let c = a + check: + bool(a == c) + block: + var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000000") + let carry = a.add(b, cfalse(Word)) - let c = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000001") - check: - bool(a == c) - block: - var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let b = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") - let carry = a.add(b, ctrue(Word)) + let c = a + check: + bool(a == c) - let c = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000001") - check: - bool(a == c) + test "Adding non-zeros - real addition": + block: + var a = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let carry = a.add(b, ctrue(Word)) - test "Adding non-zeros - fake addition": - block: - var a = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let carry = a.add(b, cfalse(Word)) + let c = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000001") + check: + bool(a == c) + block: + var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let b = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") + let carry = a.add(b, ctrue(Word)) - let c = a - check: - bool(a == c) - block: - var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let b = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") - let carry = a.add(b, cfalse(Word)) + let c = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000001") + check: + bool(a == c) - let c = a - check: - bool(a == c) + test "Adding non-zeros - fake addition": + block: + var a = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let carry = a.add(b, cfalse(Word)) - test "Addition limbs carry": - block: - var a = fromHex(BigInt[128], "0x00000000_FFFFFFFF_FFFFFFFF_FFFFFFFE") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let carry = a.add(b, ctrue(Word)) + let c = a + check: + bool(a == c) + block: + var a = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let b = fromHex(BigInt[128], "0x00000000_00000001_00000000_00000000") + let carry = a.add(b, cfalse(Word)) - let c = fromHex(BigInt[128], "0x00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF") - check: - bool(a == c) - not bool(carry) + let c = a + check: + bool(a == c) - block: - var a = fromHex(BigInt[128], "0x00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF") - let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") - let carry = a.add(b, ctrue(Word)) + test "Addition limbs carry": + block: + var a = fromHex(BigInt[128], "0x00000000_FFFFFFFF_FFFFFFFF_FFFFFFFE") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let carry = a.add(b, ctrue(Word)) - let c = fromHex(BigInt[128], "0x00000001_00000000_00000000_00000000") - check: - bool(a == c) - not bool(carry) + let c = fromHex(BigInt[128], "0x00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF") + check: + bool(a == c) + not bool(carry) -suite "Modular operations - small modulus": - # Vectors taken from Stint - https://github.com/status-im/nim-stint - test "100 mod 13": - # Test 1 word and more than 1 word - block: - let a = BigInt[7].fromUint(100'u32) - let m = BigInt[4].fromUint(13'u8) + block: + var a = fromHex(BigInt[128], "0x00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF") + let b = fromHex(BigInt[128], "0x00000000_00000000_00000000_00000001") + let carry = a.add(b, ctrue(Word)) - var r: BigInt[4] + let c = fromHex(BigInt[128], "0x00000001_00000000_00000000_00000000") + check: + bool(a == c) + not bool(carry) + + suite "Modular operations - small modulus": + # Vectors taken from Stint - https://github.com/status-im/nim-stint + test "100 mod 13": + # Test 1 word and more than 1 word + block: + let a = BigInt[7].fromUint(100'u32) + let m = BigInt[4].fromUint(13'u8) + + var r: BigInt[4] + r.reduce(a, m) + check: + bool(r == BigInt[4].fromUint(100'u8 mod 13)) + + block: # + let a = BigInt[32].fromUint(100'u32) + let m = BigInt[4].fromUint(13'u8) + + var r: BigInt[4] + r.reduce(a, m) + check: + bool(r == BigInt[4].fromUint(100'u8 mod 13)) + + block: # + let a = BigInt[64].fromUint(100'u32) + let m = BigInt[4].fromUint(13'u8) + + var r: BigInt[4] + r.reduce(a, m) + check: + bool(r == BigInt[4].fromUint(100'u8 mod 13)) + + test "2^64 mod 3": + let a = BigInt[65].fromHex("0x1_00000000_00000000") + let m = BigInt[8].fromUint(3'u8) + + var r: BigInt[8] r.reduce(a, m) check: - bool(r == BigInt[4].fromUint(100'u8 mod 13)) + bool(r == BigInt[8].fromUint(1'u8)) - block: # - let a = BigInt[32].fromUint(100'u32) - let m = BigInt[4].fromUint(13'u8) + test "1234567891234567890 mod 10": + let a = BigInt[64].fromUint(1234567891234567890'u64) + let m = BigInt[8].fromUint(10'u8) - var r: BigInt[4] + var r: BigInt[8] r.reduce(a, m) check: - bool(r == BigInt[4].fromUint(100'u8 mod 13)) + bool(r == BigInt[8].fromUint(0'u8)) - block: # - let a = BigInt[64].fromUint(100'u32) - let m = BigInt[4].fromUint(13'u8) + suite "Modular operations - small modulus - Stint specific failures highlighted by property-based testing": + # Vectors taken from Stint - https://github.com/status-im/nim-stint + test "Modulo: 65696211516342324 mod 174261910798982": + let u = 65696211516342324'u64 + let v = 174261910798982'u64 - var r: BigInt[4] + let a = BigInt[56].fromUint(u) + let m = BigInt[48].fromUint(v) + + var r: BigInt[48] r.reduce(a, m) + check: - bool(r == BigInt[4].fromUint(100'u8 mod 13)) + bool(r == BigInt[48].fromUint(u mod v)) - test "2^64 mod 3": - let a = BigInt[65].fromHex("0x1_00000000_00000000") - let m = BigInt[8].fromUint(3'u8) + test "Modulo: 15080397990160655 mod 600432699691": + let u = 15080397990160655'u64 + let v = 600432699691'u64 - var r: BigInt[8] - r.reduce(a, m) - check: - bool(r == BigInt[8].fromUint(1'u8)) + let a = BigInt[54].fromUint(u) + let m = BigInt[40].fromUint(v) - test "1234567891234567890 mod 10": - let a = BigInt[64].fromUint(1234567891234567890'u64) - let m = BigInt[8].fromUint(10'u8) + var r: BigInt[40] + r.reduce(a, m) - var r: BigInt[8] - r.reduce(a, m) - check: - bool(r == BigInt[8].fromUint(0'u8)) + check: + bool(r == BigInt[40].fromUint(u mod v)) -suite "Modular operations - small modulus - Stint specific failures highlighted by property-based testing": - # Vectors taken from Stint - https://github.com/status-im/nim-stint - test "Modulo: 65696211516342324 mod 174261910798982": - let u = 65696211516342324'u64 - let v = 174261910798982'u64 - - let a = BigInt[56].fromUint(u) - let m = BigInt[48].fromUint(v) - - var r: BigInt[48] - r.reduce(a, m) - - check: - bool(r == BigInt[48].fromUint(u mod v)) - - test "Modulo: 15080397990160655 mod 600432699691": - let u = 15080397990160655'u64 - let v = 600432699691'u64 - - let a = BigInt[54].fromUint(u) - let m = BigInt[40].fromUint(v) - - var r: BigInt[40] - r.reduce(a, m) - - check: - bool(r == BigInt[40].fromUint(u mod v)) +main() diff --git a/tests/test_bigints_multimod.nim b/tests/test_bigints_multimod.nim index e3d99d1..cbddb62 100644 --- a/tests/test_bigints_multimod.nim +++ b/tests/test_bigints_multimod.nim @@ -14,76 +14,79 @@ import ../constantine/math/[bigints_raw, bigints_checked], ../constantine/primitives/constant_time -suite "Bigints - Multiprecision modulo": - test "bitsize 237 mod bitsize 192": - let a = BigInt[237].fromHex("0x123456789012345678901234567890123456789012345678901234567890") - let m = BigInt[192].fromHex("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB") +proc main() = + suite "Bigints - Multiprecision modulo": + test "bitsize 237 mod bitsize 192": + let a = BigInt[237].fromHex("0x123456789012345678901234567890123456789012345678901234567890") + let m = BigInt[192].fromHex("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB") - let expected = BigInt[192].fromHex("0x34567890123456789012345678901234567886f8091a3087") + let expected = BigInt[192].fromHex("0x34567890123456789012345678901234567886f8091a3087") - var r: BigInt[192] - r.reduce(a, m) - - check: - bool(r == expected) - - test "bitsize 365 mod bitsize 258": - block: - let a = BigInt[365].fromHex("0x6c8ae85a6cab4bc530b91177e3f399894ff1fe335b6b3fcdc577ea4f8d754bbe71a6353e8609a4769ec8c56727a") - let m = BigInt[258].fromHex("0x2cadadfa2bb7d7141ad9728d6955ddb68a8b81ecb6a7610575bf4d6f562b09f0d") - - let expected = BigInt[258].fromHex("0xb7c8844f534bf298645dc118384e975245c1a44ba4b0bca8a04c9db0c9035b9") - - var r: BigInt[258] + var r: BigInt[192] r.reduce(a, m) check: bool(r == expected) - block: - let a = BigInt[365].fromHex("0xbf3e7574adacfcba0016a92269ef5db4a6252cda4f0493e968a83f33657b85a7d23d59630a1f5455ff426ecb9ee") - let m = BigInt[258].fromHex("0x38aa8382b17797e08a89487925eb716be55620aa482a7098b4d02a4a30a4a1178") + test "bitsize 365 mod bitsize 258": + block: + let a = BigInt[365].fromHex("0x6c8ae85a6cab4bc530b91177e3f399894ff1fe335b6b3fcdc577ea4f8d754bbe71a6353e8609a4769ec8c56727a") + let m = BigInt[258].fromHex("0x2cadadfa2bb7d7141ad9728d6955ddb68a8b81ecb6a7610575bf4d6f562b09f0d") - let expected = BigInt[258].fromHex("0x2512663958ef1b3e6e7f14ce722e72d82e10cbdd05e9fdcfb7cd5580bf074a3fe") + let expected = BigInt[258].fromHex("0xb7c8844f534bf298645dc118384e975245c1a44ba4b0bca8a04c9db0c9035b9") - var r: BigInt[258] - r.reduce(a, m) + var r: BigInt[258] + r.reduce(a, m) - check: - bool(r == expected) + check: + bool(r == expected) - block: - let a = BigInt[365].fromHex("0x16e20483c4a7f891fae2ddd77688fe72718c843ef4bc211069365a4e23bdc0b62680248fb0bf88760810de9f592b") - let m = BigInt[258].fromHex("0x315d9c9ed0df4257a2db89e907e5f8a06e26d149e058b73c6db33bdc84c1619a4") + block: + let a = BigInt[365].fromHex("0xbf3e7574adacfcba0016a92269ef5db4a6252cda4f0493e968a83f33657b85a7d23d59630a1f5455ff426ecb9ee") + let m = BigInt[258].fromHex("0x38aa8382b17797e08a89487925eb716be55620aa482a7098b4d02a4a30a4a1178") - let expected = BigInt[258].fromHex("0x1b264b514412fdfb7579204afaad1b96d09ed6e4c985baf7e96815ab1c065e88f") + let expected = BigInt[258].fromHex("0x2512663958ef1b3e6e7f14ce722e72d82e10cbdd05e9fdcfb7cd5580bf074a3fe") - var r: BigInt[258] - r.reduce(a, m) + var r: BigInt[258] + r.reduce(a, m) - check: - bool(r == expected) + check: + bool(r == expected) - test "bitsize 1955 mod bitsize 459": - let a = BigInt[1955].fromHex("0x4f688e286a7c6e2b64663d8925c2f686994f2b90d58e7a843087c676c2c614ebab3eef9c765a88fe597b23b0e1fb28c812627366020edeafeefd0bf67a95215b4335412e2bd623b4cf7b69e669e1a8e782ab9a3e5fd443f10f459eed4ec9bd61821d94da82e937989245d481612b83b75d6d393e5de2258ac92aec7cd6e4f12c6b035e1fac3ef22851a8e211232b57db7551c03a88e9272411eea86e15c989be9d2962d5ae32ca35b18060212aaf6599b5a5f2416e436f009728b4017f87f70f4e528c9a33042b6810040c1e64457d56695d03b701540a5537c8cf781ff2ea4be2aa6daf1a5f2f0874a1cf495485a01254c2e2f4a") - let m = BigInt[459].fromHex("0x47304803a4a8c31e18287ad51c1ac7546c42e23206e9dc43e51eff5fa003f44bd08e542ec2659c405bfa4c9eb518ada943412767361029a902b") + block: + let a = BigInt[365].fromHex("0x16e20483c4a7f891fae2ddd77688fe72718c843ef4bc211069365a4e23bdc0b62680248fb0bf88760810de9f592b") + let m = BigInt[258].fromHex("0x315d9c9ed0df4257a2db89e907e5f8a06e26d149e058b73c6db33bdc84c1619a4") - let expected = BigInt[459].fromHex("0x1f039dfe7c9da071d578b3b852db3916f4d79f6169818085994cbc41610abb7abb96e10d1126313cc281a87c309c2dd43bed745a9603f3c606c") + let expected = BigInt[258].fromHex("0x1b264b514412fdfb7579204afaad1b96d09ed6e4c985baf7e96815ab1c065e88f") - var r: BigInt[459] - r.reduce(a, m) + var r: BigInt[258] + r.reduce(a, m) - check: - bool(r == expected) + check: + bool(r == expected) - test "bitsize 2346 mod bitsize 97": - let a = BigInt[2346].fromHex("0x1b5efa688e4124a71edd035f106c6ea81bafd78f610cd59d46fc6cda548fd970dde6b91c6fa10ab6d198026dea3c46c41495294082f2acc8210fd7ebfb25fdc6ce8131676ab0d749c5a4a83dd08172b3849df30304685192708ff0b510600cbf87be3179ce704adc43f2c9b22ba28c77f0a364fa1a96344d7f338227a8f346c0e721bc1312f53cebfc20fd0763ec039aa83a77ba489056ebee2a462058f1daffec9b5df29474f638185c6684729482a29764b46a5487e159fc4eedda5018d3d18ae1c0c6503ebbbd859b4dff3e09b6567b752d51c9733fc822b2758b69ffd65974a8fbf4ad25a40761bb9b9b6a1f886928fe08f9c1571fe3e3987b15e37208a22f64e2c3ff75a36815b7906fc2a52f7bd32d15e8b0441e8c39ae9127d80946e146db5cd2738") - let m = BigInt[97].fromHex("0x1100d0717f9fff44c6cc7442e") + test "bitsize 1955 mod bitsize 459": + let a = BigInt[1955].fromHex("0x4f688e286a7c6e2b64663d8925c2f686994f2b90d58e7a843087c676c2c614ebab3eef9c765a88fe597b23b0e1fb28c812627366020edeafeefd0bf67a95215b4335412e2bd623b4cf7b69e669e1a8e782ab9a3e5fd443f10f459eed4ec9bd61821d94da82e937989245d481612b83b75d6d393e5de2258ac92aec7cd6e4f12c6b035e1fac3ef22851a8e211232b57db7551c03a88e9272411eea86e15c989be9d2962d5ae32ca35b18060212aaf6599b5a5f2416e436f009728b4017f87f70f4e528c9a33042b6810040c1e64457d56695d03b701540a5537c8cf781ff2ea4be2aa6daf1a5f2f0874a1cf495485a01254c2e2f4a") + let m = BigInt[459].fromHex("0x47304803a4a8c31e18287ad51c1ac7546c42e23206e9dc43e51eff5fa003f44bd08e542ec2659c405bfa4c9eb518ada943412767361029a902b") - let expected = BigInt[97].fromHex("0x0104ea05300eeb05cd374197b6") + let expected = BigInt[459].fromHex("0x1f039dfe7c9da071d578b3b852db3916f4d79f6169818085994cbc41610abb7abb96e10d1126313cc281a87c309c2dd43bed745a9603f3c606c") - var r: BigInt[97] - r.reduce(a, m) + var r: BigInt[459] + r.reduce(a, m) - check: - bool(r == expected) + check: + bool(r == expected) + + test "bitsize 2346 mod bitsize 97": + let a = BigInt[2346].fromHex("0x1b5efa688e4124a71edd035f106c6ea81bafd78f610cd59d46fc6cda548fd970dde6b91c6fa10ab6d198026dea3c46c41495294082f2acc8210fd7ebfb25fdc6ce8131676ab0d749c5a4a83dd08172b3849df30304685192708ff0b510600cbf87be3179ce704adc43f2c9b22ba28c77f0a364fa1a96344d7f338227a8f346c0e721bc1312f53cebfc20fd0763ec039aa83a77ba489056ebee2a462058f1daffec9b5df29474f638185c6684729482a29764b46a5487e159fc4eedda5018d3d18ae1c0c6503ebbbd859b4dff3e09b6567b752d51c9733fc822b2758b69ffd65974a8fbf4ad25a40761bb9b9b6a1f886928fe08f9c1571fe3e3987b15e37208a22f64e2c3ff75a36815b7906fc2a52f7bd32d15e8b0441e8c39ae9127d80946e146db5cd2738") + let m = BigInt[97].fromHex("0x1100d0717f9fff44c6cc7442e") + + let expected = BigInt[97].fromHex("0x0104ea05300eeb05cd374197b6") + + var r: BigInt[97] + r.reduce(a, m) + + check: + bool(r == expected) + +main() diff --git a/tests/test_io.nim b/tests/test_io.nim index 0933fef..198b2ce 100644 --- a/tests/test_io.nim +++ b/tests/test_io.nim @@ -14,39 +14,30 @@ import unittest, random, randomize(0xDEADBEEF) # Random seed for reproducibility type T = BaseType -suite "IO": - test "Parsing raw integers": - block: # Sanity check - let x = 0'u64 - let x_bytes = cast[array[8, byte]](x) - let big = BigInt[64].fromRawUint(x_bytes, cpuEndian) +proc main() = + suite "IO": + test "Parsing raw integers": + block: # Sanity check + let x = 0'u64 + let x_bytes = cast[array[8, byte]](x) + let big = BigInt[64].fromRawUint(x_bytes, cpuEndian) - check: - T(big.limbs[0]) == 0 - T(big.limbs[1]) == 0 + check: + T(big.limbs[0]) == 0 + T(big.limbs[1]) == 0 - test "Parsing and dumping round-trip on uint64": - block: - # "Little-endian" - 2^63 - let x = 1'u64 shl 63 - let x_bytes = cast[array[8, byte]](x) - let big = BigInt[64].fromRawUint(x_bytes, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern + test "Parsing and dumping round-trip on uint64": + block: + # "Little-endian" - 2^63 + let x = 1'u64 shl 63 + let x_bytes = cast[array[8, byte]](x) + 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) - check: x_bytes == r_bytes + var r_bytes: array[8, byte] + dumpRawUint(r_bytes, big, littleEndian) + check: x_bytes == r_bytes - block: # "Little-endian" - single random - let x = uint64 rand(0..high(int)) - let x_bytes = cast[array[8, byte]](x) - 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) - check: x_bytes == r_bytes - - block: # "Little-endian" - 10 random cases - for _ in 0 ..< 10: + block: # "Little-endian" - single random let x = uint64 rand(0..high(int)) let x_bytes = cast[array[8, byte]](x) let big = BigInt[64].fromRawUint(x_bytes, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern @@ -55,24 +46,36 @@ suite "IO": dumpRawUint(r_bytes, big, littleEndian) check: x_bytes == r_bytes - test "Round trip on elliptic curve constants": - block: # Secp256k1 - https://en.bitcoin.it/wiki/Secp256k1 - const p = "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" - let x = BigInt[256].fromHex(p) - let hex = x.dumpHex(bigEndian) + block: # "Little-endian" - 10 random cases + for _ in 0 ..< 10: + let x = uint64 rand(0..high(int)) + let x_bytes = cast[array[8, byte]](x) + let big = BigInt[64].fromRawUint(x_bytes, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern - check: p == hex + var r_bytes: array[8, byte] + dumpRawUint(r_bytes, big, littleEndian) + check: x_bytes == r_bytes - block: # BN254 - https://github.com/ethereum/py_ecc/blob/master/py_ecc/fields/field_properties.py - const p = "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47" - let x = BigInt[254].fromHex(p) - let hex = x.dumpHex(bigEndian) + test "Round trip on elliptic curve constants": + block: # Secp256k1 - https://en.bitcoin.it/wiki/Secp256k1 + const p = "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" + let x = BigInt[256].fromHex(p) + let hex = x.dumpHex(bigEndian) - check: p == hex + 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 = BigInt[381].fromHex(p) - let hex = x.dumpHex(bigEndian) + block: # BN254 - https://github.com/ethereum/py_ecc/blob/master/py_ecc/fields/field_properties.py + const p = "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47" + let x = BigInt[254].fromHex(p) + let hex = x.dumpHex(bigEndian) - check: p == hex + 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 = BigInt[381].fromHex(p) + let hex = x.dumpHex(bigEndian) + + check: p == hex + +main() diff --git a/tests/test_primitives.nim b/tests/test_primitives.nim index f82425e..ee8ef31 100644 --- a/tests/test_primitives.nim +++ b/tests/test_primitives.nim @@ -15,173 +15,176 @@ randomize(0xDEADBEEF) template undistinct[T](x: Ct[T]): T = T(x) -suite "Constant-time unsigned integers": - test "High - getting the biggest representable number": - check: - high(Ct[byte]).undistinct == 0xFF.byte - high(Ct[uint8]).undistinct == 0xFF'u8 - - high(Ct[uint16]).undistinct == 0xFFFF'u16 - high(Ct[uint32]).undistinct == 0xFFFFFFFF'u32 - high(Ct[uint64]).undistinct == 0xFFFFFFFF_FFFFFFFF'u64 - - test "bitwise `and`, `or`, `xor`, `not`": - let x1 = rand(high(int)).uint64 - let y1 = rand(high(int)).uint64 - let x2 = rand(high(int)).uint64 - let y2 = rand(high(int)).uint64 - let x3 = rand(high(int)).uint64 - let y3 = rand(high(int)).uint64 - template bitwise_check(op: untyped): untyped = - block: - check: - op(ct(0'u32), ct(0'u32)).undistinct == op(0'u32, 0'u32) - op(ct(0'u32), ct(1'u32)).undistinct == op(0'u32, 1'u32) - op(ct(1234'u64), ct(5678'u64)).undistinct == op(1234'u64, 5678'u64) - - op(x1.ct, y1.ct).undistinct == op(x1, y1) - op(x2.ct, y2.ct).undistinct == op(x2, y2) - op(x3.ct, y3.ct).undistinct == op(x3, y3) - bitwise_check(`and`) - bitwise_check(`or`) - bitwise_check(`xor`) - - block: +proc main() = + suite "Constant-time unsigned integers": + test "High - getting the biggest representable number": check: - not(ct(0'u32)).undistinct == not 0'u32 - not(ct(1'u32)).undistinct == not 1'u32 - not(ct(1234'u64)).undistinct == not 1234'u64 - not(ct(5678'u64)).undistinct == not 5678'u64 - not(ct(x1)).undistinct == not x1 - not(ct(x2)).undistinct == not x2 - not(ct(x3)).undistinct == not x3 - not(ct(y1)).undistinct == not y1 - not(ct(y2)).undistinct == not y2 - not(ct(y3)).undistinct == not y3 + high(Ct[byte]).undistinct == 0xFF.byte + high(Ct[uint8]).undistinct == 0xFF'u8 - test "Logical shifts": - let x1 = rand(high(int)).uint64 - let y1 = rand(high(int)).uint64 - let x2 = rand(high(int)).uint64 - let y2 = rand(high(int32)).uint64 - let x3 = rand(high(int32)).uint64 - let y3 = rand(high(int32)).uint64 + high(Ct[uint16]).undistinct == 0xFFFF'u16 + high(Ct[uint32]).undistinct == 0xFFFFFFFF'u32 + high(Ct[uint64]).undistinct == 0xFFFFFFFF_FFFFFFFF'u64 - let s1 = rand(10) - let s2 = rand(10) - let s3 = rand(10) + test "bitwise `and`, `or`, `xor`, `not`": + let x1 = rand(high(int)).uint64 + let y1 = rand(high(int)).uint64 + let x2 = rand(high(int)).uint64 + let y2 = rand(high(int)).uint64 + let x3 = rand(high(int)).uint64 + let y3 = rand(high(int)).uint64 + template bitwise_check(op: untyped): untyped = + block: + check: + op(ct(0'u32), ct(0'u32)).undistinct == op(0'u32, 0'u32) + op(ct(0'u32), ct(1'u32)).undistinct == op(0'u32, 1'u32) + op(ct(1234'u64), ct(5678'u64)).undistinct == op(1234'u64, 5678'u64) + + op(x1.ct, y1.ct).undistinct == op(x1, y1) + op(x2.ct, y2.ct).undistinct == op(x2, y2) + op(x3.ct, y3.ct).undistinct == op(x3, y3) + bitwise_check(`and`) + bitwise_check(`or`) + bitwise_check(`xor`) - template shift_check(op: untyped): untyped = block: check: - op(ct(0'u32), 1).undistinct == op(0'u32, 1) - op(ct(1'u32), 2).undistinct == op(1'u32, 2) - op(ct(1234'u64), 3).undistinct == op(1234'u64, 3) - op(ct(2'u64^30), 1).undistinct == op(2'u64^30, 1) - op(ct(2'u64^31 + 1), 1).undistinct == op(2'u64^31 + 1, 1) - op(ct(2'u64^32), 1).undistinct == op(2'u64^32, 1) + not(ct(0'u32)).undistinct == not 0'u32 + not(ct(1'u32)).undistinct == not 1'u32 + not(ct(1234'u64)).undistinct == not 1234'u64 + not(ct(5678'u64)).undistinct == not 5678'u64 + not(ct(x1)).undistinct == not x1 + not(ct(x2)).undistinct == not x2 + not(ct(x3)).undistinct == not x3 + not(ct(y1)).undistinct == not y1 + not(ct(y2)).undistinct == not y2 + not(ct(y3)).undistinct == not y3 - op(x1.ct, s1).undistinct == op(x1, s1) - op(x2.ct, s2).undistinct == op(x2, s2) - op(x3.ct, s3).undistinct == op(x3, s3) + test "Logical shifts": + let x1 = rand(high(int)).uint64 + let y1 = rand(high(int)).uint64 + let x2 = rand(high(int)).uint64 + let y2 = rand(high(int32)).uint64 + let x3 = rand(high(int32)).uint64 + let y3 = rand(high(int32)).uint64 + + let s1 = rand(10) + let s2 = rand(10) + let s3 = rand(10) + + template shift_check(op: untyped): untyped = + block: + check: + op(ct(0'u32), 1).undistinct == op(0'u32, 1) + op(ct(1'u32), 2).undistinct == op(1'u32, 2) + op(ct(1234'u64), 3).undistinct == op(1234'u64, 3) + op(ct(2'u64^30), 1).undistinct == op(2'u64^30, 1) + op(ct(2'u64^31 + 1), 1).undistinct == op(2'u64^31 + 1, 1) + op(ct(2'u64^32), 1).undistinct == op(2'u64^32, 1) + + op(x1.ct, s1).undistinct == op(x1, s1) + op(x2.ct, s2).undistinct == op(x2, s2) + op(x3.ct, s3).undistinct == op(x3, s3) - op(y1.ct, s1).undistinct == op(y1, s1) - op(y2.ct, s2).undistinct == op(y2, s2) - op(y3.ct, s3).undistinct == op(y3, s3) + op(y1.ct, s1).undistinct == op(y1, s1) + op(y2.ct, s2).undistinct == op(y2, s2) + op(y3.ct, s3).undistinct == op(y3, s3) - shift_check(`shl`) - shift_check(`shr`) + shift_check(`shl`) + shift_check(`shr`) - test "Operators `+`, `-`, `*`": - let x1 = rand(high(int)).uint64 - let y1 = rand(high(int)).uint64 - let x2 = rand(high(int)).uint64 - let y2 = rand(high(int)).uint64 - let x3 = rand(high(int)).uint64 - let y3 = rand(high(int)).uint64 - template operator_check(op: untyped): untyped = - block: - check: - op(ct(0'u32), ct(0'u32)).undistinct == op(0'u32, 0'u32) - op(ct(0'u32), ct(1'u32)).undistinct == op(0'u32, 1'u32) - op(ct(1234'u64), ct(5678'u64)).undistinct == op(1234'u64, 5678'u64) + test "Operators `+`, `-`, `*`": + let x1 = rand(high(int)).uint64 + let y1 = rand(high(int)).uint64 + let x2 = rand(high(int)).uint64 + let y2 = rand(high(int)).uint64 + let x3 = rand(high(int)).uint64 + let y3 = rand(high(int)).uint64 + template operator_check(op: untyped): untyped = + block: + check: + op(ct(0'u32), ct(0'u32)).undistinct == op(0'u32, 0'u32) + op(ct(0'u32), ct(1'u32)).undistinct == op(0'u32, 1'u32) + op(ct(1234'u64), ct(5678'u64)).undistinct == op(1234'u64, 5678'u64) - op(x1.ct, y1.ct).undistinct == op(x1, y1) - op(x2.ct, y2.ct).undistinct == op(x2, y2) - op(x3.ct, y3.ct).undistinct == op(x3, y3) - operator_check(`+`) - operator_check(`-`) - operator_check(`*`) + op(x1.ct, y1.ct).undistinct == op(x1, y1) + op(x2.ct, y2.ct).undistinct == op(x2, y2) + op(x3.ct, y3.ct).undistinct == op(x3, y3) + operator_check(`+`) + operator_check(`-`) + operator_check(`*`) - test "Unary `-`, returning the 2-complement of an unsigned integer": - let x1 = rand(high(int)).uint64 - let y1 = rand(high(int)).uint64 - let x2 = rand(high(int)).uint64 - let y2 = rand(high(int)).uint64 - let x3 = rand(high(int)).uint64 - let y3 = rand(high(int)).uint64 - check: - (-ct(0'u32)).undistinct == 0 - (-high(Ct[uint32])).undistinct == 1'u32 - (-ct(0x80000000'u32)).undistinct == 0x80000000'u32 # This is low(int32) == 0b10000..0000 + test "Unary `-`, returning the 2-complement of an unsigned integer": + let x1 = rand(high(int)).uint64 + let y1 = rand(high(int)).uint64 + let x2 = rand(high(int)).uint64 + let y2 = rand(high(int)).uint64 + let x3 = rand(high(int)).uint64 + let y3 = rand(high(int)).uint64 + check: + (-ct(0'u32)).undistinct == 0 + (-high(Ct[uint32])).undistinct == 1'u32 + (-ct(0x80000000'u32)).undistinct == 0x80000000'u32 # This is low(int32) == 0b10000..0000 - undistinct(-x1.ct) == undistinct(not(x1.ct) + ct(1'u64)) - undistinct(-x2.ct) == undistinct(not(x2.ct) + ct(1'u64)) - undistinct(-x3.ct) == undistinct(not(x3.ct) + ct(1'u64)) - undistinct(-y1.ct) == undistinct(not(y1.ct) + ct(1'u64)) - undistinct(-y2.ct) == undistinct(not(y2.ct) + ct(1'u64)) - undistinct(-y3.ct) == undistinct(not(y3.ct) + ct(1'u64)) + undistinct(-x1.ct) == undistinct(not(x1.ct) + ct(1'u64)) + undistinct(-x2.ct) == undistinct(not(x2.ct) + ct(1'u64)) + undistinct(-x3.ct) == undistinct(not(x3.ct) + ct(1'u64)) + undistinct(-y1.ct) == undistinct(not(y1.ct) + ct(1'u64)) + undistinct(-y2.ct) == undistinct(not(y2.ct) + ct(1'u64)) + undistinct(-y3.ct) == undistinct(not(y3.ct) + ct(1'u64)) -suite "Constant-time booleans": - test "Boolean not": - check: - not(ctrue(uint32)).bool == false - not(cfalse(uint32)).bool == true + suite "Constant-time booleans": + test "Boolean not": + check: + not(ctrue(uint32)).bool == false + not(cfalse(uint32)).bool == true - test "Comparison": - check: - bool(ct(0'u32) != ct(0'u32)) == false - bool(ct(0'u32) != ct(1'u32)) == true + test "Comparison": + check: + bool(ct(0'u32) != ct(0'u32)) == false + bool(ct(0'u32) != ct(1'u32)) == true - bool(ct(10'u32) == ct(10'u32)) == true - bool(ct(10'u32) != ct(20'u32)) == true + bool(ct(10'u32) == ct(10'u32)) == true + bool(ct(10'u32) != ct(20'u32)) == true - bool(ct(10'u32) <= ct(10'u32)) == true - bool(ct(10'u32) <= ct(20'u32)) == true - bool(ct(10'u32) <= ct(5'u32)) == false - bool(ct(10'u32) <= ct(0xFFFFFFFF'u32)) == true + bool(ct(10'u32) <= ct(10'u32)) == true + bool(ct(10'u32) <= ct(20'u32)) == true + bool(ct(10'u32) <= ct(5'u32)) == false + bool(ct(10'u32) <= ct(0xFFFFFFFF'u32)) == true - bool(ct(10'u32) < ct(10'u32)) == false - bool(ct(10'u32) < ct(20'u32)) == true - bool(ct(10'u32) < ct(5'u32)) == false - bool(ct(10'u32) < ct(0xFFFFFFFF'u32)) == true + bool(ct(10'u32) < ct(10'u32)) == false + bool(ct(10'u32) < ct(20'u32)) == true + bool(ct(10'u32) < ct(5'u32)) == false + bool(ct(10'u32) < ct(0xFFFFFFFF'u32)) == true - bool(ct(10'u32) > ct(10'u32)) == false - bool(ct(10'u32) > ct(20'u32)) == false - bool(ct(10'u32) > ct(5'u32)) == true - bool(ct(10'u32) > ct(0xFFFFFFFF'u32)) == false + bool(ct(10'u32) > ct(10'u32)) == false + bool(ct(10'u32) > ct(20'u32)) == false + bool(ct(10'u32) > ct(5'u32)) == true + bool(ct(10'u32) > ct(0xFFFFFFFF'u32)) == false - bool(ct(10'u32) >= ct(10'u32)) == true - bool(ct(10'u32) >= ct(20'u32)) == false - bool(ct(10'u32) >= ct(5'u32)) == true - bool(ct(10'u32) >= ct(0xFFFFFFFF'u32)) == false + bool(ct(10'u32) >= ct(10'u32)) == true + bool(ct(10'u32) >= ct(20'u32)) == false + bool(ct(10'u32) >= ct(5'u32)) == true + bool(ct(10'u32) >= ct(0xFFFFFFFF'u32)) == false - test "Multiplexer/selector - mux(ctl, x, y) <=> ctl? x: y": - let u = 10'u32.ct - let v = 20'u32.ct - let w = 5'u32.ct + test "Multiplexer/selector - mux(ctl, x, y) <=> ctl? x: y": + let u = 10'u32.ct + let v = 20'u32.ct + let w = 5'u32.ct - let y = ctrue(uint32) - let n = cfalse(uint32) + let y = ctrue(uint32) + let n = cfalse(uint32) - check: - bool(mux(y, u, v) == u) - bool(mux(n, u, v) == v) + check: + bool(mux(y, u, v) == u) + bool(mux(n, u, v) == v) - bool(mux(y, u, w) == u) - bool(mux(n, u, w) == w) + bool(mux(y, u, w) == u) + bool(mux(n, u, w) == w) - bool(mux(y, v, w) == v) - bool(mux(n, v, w) == w) + bool(mux(y, v, w) == v) + bool(mux(n, v, w) == w) + +main()