Remove ttmath and allow compilation to C, change "private" field names.

This commit is contained in:
mratsim 2018-03-21 15:54:41 +01:00
parent 98e8886f86
commit 92bdd41643
9 changed files with 65 additions and 60 deletions

View File

@ -9,7 +9,7 @@ srcDir = "src"
requires "nim >= 0.18.0", "keccak_tiny >= 0.1.0", "ttmath >= 0.1.0", "nimSHA2", "secp256k1"
proc test(name: string, lang: string = "cpp") =
proc test(name: string, lang: string = "c") =
if not dirExists "build":
mkDir "build"
if not dirExists "nimcache":
@ -19,9 +19,12 @@ proc test(name: string, lang: string = "cpp") =
switch("out", ("./build/" & name))
setCommand lang, "tests/" & name & ".nim"
task test, "Run all tests - libsecp256k1 backend":
task test, "Run all tests - C & libsecp256k1 backend":
test "all_tests"
task test_cpp, "Run all tests - C++ & libsecp256k1 backend":
test "all_tests", "cpp"
task test_backend_native, "Run all tests - pure Nim backend":
switch("define", "backend_native")
test "all_tests"
test "all_tests", "cpp"

View File

@ -7,7 +7,7 @@
#
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import ../datatypes
import ../datatypes, ../private/conversion_bytes
import secp256k1, keccak_tiny
const SECP256K1_CONTEXT_ALL = SECP256K1_CONTEXT_VERIFY or SECP256K1_CONTEXT_SIGN

View File

@ -8,42 +8,19 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./private/conversion_bytes
export toHex, hexToByteArrayBE, hexToSeqByteBE
# Note: Fields are intentionally kept private
# Note: Fields F should be private, it is intentionally ugly to directly access them
# See private field access issue: https://github.com/nim-lang/Nim/issues/7390
type
PublicKey* = object
Fraw_key: array[64, byte]
Fraw_key*: array[64, byte]
PrivateKey* = object
Fraw_key: array[32, byte]
Fpublic_key: PublicKey
Fraw_key*: array[32, byte]
Fpublic_key*: PublicKey
Signature* {.packed.}= object
Fr: array[32, byte]
Fs: array[32, byte]
Fv: range[0.byte .. 1.byte]
Fr*: array[32, byte]
Fs*: array[32, byte]
Fv*: range[0.byte .. 1.byte] # This should be 27..28 as per Ethereum but it's 0..1 in eth-keys ...
# "Public" accessors, only exposed to internal modules
template genAccessors(name: untyped, fieldType, objType: typedesc): untyped =
# Access
proc name*(obj: objType): fieldType {.noSideEffect, inline, noInit.} =
obj.`F name`
# Assignement
proc `name=`*(obj: var objType, value: fieldType): fieldType {.noSideEffect, inline.} =
obj.`F name` = value
# Mutable
proc `name`*(obj: var objType): var fieldType {.noSideEffect, inline.} =
obj.`F name`
genAccessors(raw_key, array[64, byte], PublicKey)
genAccessors(raw_key, array[32, byte], PrivateKey)
genAccessors(public_key, PublicKey, PrivateKey)
genAccessors(s, array[32, byte], Signature)
genAccessors(r, array[32, byte], Signature)
genAccessors(v, range[0.byte .. 1.byte], Signature)

View File

@ -13,7 +13,7 @@
# Note: for now only a native pure Nim backend is supported
# In the future alternative, proven crypto backend will be added like libsecpk1
import ./datatypes
import ./datatypes, ./private/conversion_bytes
import keccak_tiny
@ -30,8 +30,8 @@ else:
# Initialization
proc initPrivateKey*(hexString: string): PrivateKey {.noInit.} =
hexToByteArrayBE(hexString, result.raw_key)
result.public_key = private_key_to_public_key(result)
hexToByteArrayBE(hexString, result.Fraw_key)
result.Fpublic_key = private_key_to_public_key(result)
proc initPublicKey*(hexString: string): PublicKey {.noInit.} =
var b: array[65, byte]
@ -67,4 +67,4 @@ proc sign_msg*(key: PrivateKey, message_hash: Hash[256]): Signature {.inline.} =
ecdsa_sign(key, message_hash)
proc `$`*(key: PrivateKey): string {.inline.} =
key.raw_key.toHex()
key.Fraw_key.toHex()

View File

@ -9,9 +9,15 @@
when defined(backend_native):
echo "\nBackend tested: native\n"
when defined(c):
{.fatal: "The native backend require C++ compilation for ttmath.}".}
else:
echo "\nBackend tested: libsecp256k1\n"
when not defined(cpp):
echo "C backend chosen. Skipping ttmath_hex_bytes_conversion test"
import ./test_hex_bytes_conversion,
./test_private_public_key_consistency,
when defined(cpp):
import ./test_ttmath_hex_bytes_conversion
import ./test_private_public_key_consistency,
./test_key_and_signature_datastructures

View File

@ -41,14 +41,16 @@ let
MSG* = "message"
MSGHASH* = keccak256(MSG)
# Conversion done through https://www.mobilefish.com/services/big_number/big_number.php
let
alice* = testKeySig(
privkey: "9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501",
pubkey: "5eed5fa3a67696c334762bb4823e585e2ee579aba3558d9955296d6c04541b426078dbd48d74af1fd0c72aa1a05147cf17be6b60bdbed6ba19b08ec28445b0ca",
raw_sig: (
v: 1,
r: "80536744857756143861726945576089915884233437828013729338039544043241440681784",
s: "1902566422691403459035240420865094128779958320521066670269403689808757640701"
r: "B20E2EA5D3CBAA83C1E0372F110CF12535648613B479B64C1A8C1A20C5021F38", # Decimal "80536744857756143861726945576089915884233437828013729338039544043241440681784",
s: "434D07EC5795E3F789794351658E80B7FAF47A46328F41E019D7B853745CDFD" # Decimal "1902566422691403459035240420865094128779958320521066670269403689808757640701"
)
)
@ -57,8 +59,8 @@ let
pubkey: "347746ccb908e583927285fa4bd202f08e2f82f09c920233d89c47c79e48f937d049130e3d1c14cf7b21afefc057f71da73dec8e8ff74ff47dc6a574ccd5d570",
raw_sig: (
v: 1,
r: "41741612198399299636429810387160790514780876799439767175315078161978521003886",
s: "47545396818609319588074484786899049290652725314938191835667190243225814114102"
r: "5C48EA4F0F2257FA23BD25E6FCB0B75BBE2FF9BBDA0167118DAB2BB6E31BA76E", # Decimal "41741612198399299636429810387160790514780876799439767175315078161978521003886",
s: "691DBDAF2A231FC9958CD8EDD99507121F8184042E075CF10F98BA88ABFF1F36" # Decimal "47545396818609319588074484786899049290652725314938191835667190243225814114102"
)
)
@ -67,7 +69,7 @@ let
pubkey: "c06641f0d04f64dba13eac9e52999f2d10a1ff0ca68975716b6583dee0318d91e7c2aed363ed22edeba2215b03f6237184833fd7d4ad65f75c2c1d5ea0abecc0",
raw_sig: (
v: 0,
r: "84467545608142925331782333363288012579669270632210954476013542647119929595395",
s: "43529886636775750164425297556346136250671451061152161143648812009114516499167"
r: "BABEEFC5082D3CA2E0BC80532AB38F9CFB196FB9977401B2F6A98061F15ED603", # Decimal "84467545608142925331782333363288012579669270632210954476013542647119929595395",
s: "603D0AF084BF906B2CDF6CDDE8B2E1C3E51A41AF5E9ADEC7F3643B3F1AA2AADF" # Decimal "43529886636775750164425297556346136250671451061152161143648812009114516499167"
)
)

View File

@ -7,7 +7,7 @@
#
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import ../src/eth_keys,
import ../src/eth_keys, ../src/private/conversion_bytes,
./config
import unittest
@ -19,9 +19,9 @@ suite "Test key and signature data structure":
pk = initPrivateKey(person.privkey)
signature = pk.sign_msg(MSG)
check: signature.v == person.raw_sig.v
check: signature.r == person.raw_sig.r.u256
check: signature.s == person.raw_sig.s.u256
check: signature.Fv == person.raw_sig.v
check: signature.Fr == hexToByteArrayBE[32](person.raw_sig.r)
check: signature.Fs == hexToByteArrayBE[32](person.raw_sig.s)
test "Signing from private key object (ported from official eth-keys)":
for person in [alice, bob, eve]:
@ -29,7 +29,7 @@ suite "Test key and signature data structure":
pk = initPrivateKey(person.privkey)
signature = pk.sign_msg(MSG)
check: verify_msg(pk.public_key, MSG, signature)
check: verify_msg(pk.Fpublic_key, MSG, signature)
test "Hash signing from private key object":
@ -38,9 +38,9 @@ suite "Test key and signature data structure":
pk = initPrivateKey(person.privkey)
signature = pk.sign_msg(MSG)
check: signature.v == person.raw_sig.v
check: signature.r == person.raw_sig.r.u256
check: signature.s == person.raw_sig.s.u256
check: signature.Fv == person.raw_sig.v
check: signature.Fr == hexToByteArrayBE[32](person.raw_sig.r)
check: signature.Fs == hexToByteArrayBE[32](person.raw_sig.s)
test "Hash signing from private key object (ported from official eth-keys)":
for person in [alice, bob, eve]:
@ -48,7 +48,7 @@ suite "Test key and signature data structure":
pk = initPrivateKey(person.privkey)
signature = pk.sign_msg(MSGHASH)
check: verify_msg(pk.public_key, MSGHASH, signature)
check: verify_msg(pk.Fpublic_key, MSGHASH, signature)
test "Recover public key from message":
for person in [alice, bob, eve]:
@ -58,7 +58,7 @@ suite "Test key and signature data structure":
recovered_pubkey = recover_pubkey_from_msg(MSG, signature)
check: pk.public_key == recovered_pubkey
check: pk.Fpublic_key == recovered_pubkey
test "Recover public key from message hash":
for person in [alice, bob, eve]:
@ -68,4 +68,4 @@ suite "Test key and signature data structure":
recovered_pubkey = recover_pubkey_from_msg(MSGHASH, signature)
check: pk.public_key == recovered_pubkey
check: pk.Fpublic_key == recovered_pubkey

View File

@ -17,6 +17,6 @@ suite "Testing private -> public key conversion":
for person in [alice, bob, eve]:
let privkey = initPrivateKey(person.privkey)
let computed_pubkey = $privkey.public_key
let computed_pubkey = $privkey.Fpublic_key
check: computed_pubkey == person.pubkey
check: computed_pubkey == person.pubkey

View File

@ -10,6 +10,7 @@
import ../src/private/[conversion_bytes, conversion_ttmath]
import unittest, ttmath, strutils # TODO remove ttmath needs if backend libsecp256k1
import ./config
suite "Testing conversion functions: Hex, Bytes, Endianness":
let
@ -27,3 +28,19 @@ suite "Testing conversion functions: Hex, Bytes, Endianness":
test "uint256 -> big-endian array -> hex":
check: SECPK1_N.toByteArrayBE.toHex == SECPK1_N_HEX
suite "Confirming consistency: hex vs decimal conversion":
# Conversion done through https://www.mobilefish.com/services/big_number/big_number.php
test "Alice signature":
check: alice.raw_sig.r.hexToUInt256 == "80536744857756143861726945576089915884233437828013729338039544043241440681784".u256
check: alice.raw_sig.s.hexToUInt256 == "1902566422691403459035240420865094128779958320521066670269403689808757640701".u256
test "Bob signature":
check: alice.raw_sig.r.hexToUInt256 == "41741612198399299636429810387160790514780876799439767175315078161978521003886".u256
check: alice.raw_sig.s.hexToUInt256 == "47545396818609319588074484786899049290652725314938191835667190243225814114102".u256
test "Eve signature":
check: alice.raw_sig.r.hexToUInt256 == "84467545608142925331782333363288012579669270632210954476013542647119929595395".u256
check: alice.raw_sig.s.hexToUInt256 == "43529886636775750164425297556346136250671451061152161143648812009114516499167".u256