This is an automated email from the ASF dual-hosted git repository.

sandreoli pushed a commit to branch issue7-schnorr-python-wrapper
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-MPC.git

commit 33ea100ab5236329bc463ff8eed34dffc7b18f1c
Author: Samuele Andreoli <[email protected]>
AuthorDate: Tue Feb 18 14:04:05 2020 +0000

    Refactor benchmarks
---
 python/CMakeLists.txt                           |  1 +
 python/README.md                                | 45 ++++++++++++++-
 python/{ => benchmark}/CMakeLists.txt           |  9 +--
 python/benchmark/bench.py                       | 62 +++++++++++++++++++++
 python/{bench_mpc.py => benchmark/bench_mta.py} | 73 +++++++------------------
 python/benchmark/bench_schnorr.py               | 53 ++++++++++++++++++
 python/benchmark/context.py                     | 25 +++++++++
 7 files changed, 206 insertions(+), 62 deletions(-)

diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index d7ed21c..5971f47 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -20,3 +20,4 @@ include(PythonSiteDirs)
 add_subdirectory(amcl)
 add_subdirectory(test)
 add_subdirectory(examples)
+add_subdirectory(benchmark)
diff --git a/python/README.md b/python/README.md
index 8489444..1075b2d 100644
--- a/python/README.md
+++ b/python/README.md
@@ -2,8 +2,49 @@
 
 This directory contains the C code wrapper for Python.
 
-After installation to run an example
+## Tests
 
+### Automatic run
+
+The simplest way to run the wrapper tests is using the Makefile
+in the build directory or in the python build directory
+
+```sh
+make test
+```
+
+### Manual run
+
+Individual tests can be executed after installation using
+
+```sh
+./test_mta.py
+```
+
+To run individual tests manually before installation add
+the build `src` directory to your system dynamic library path.
+
+e.g. for Linux
+
+```sh
+export LD_LIBRARY_PATH=<build_dir>/src/:$LD_LIBRARY_PATH
 ```
+
+## Benchmark and examples
+
+Individual benchmarks or examples can be executed after
+installation using
+
+```sh
 ./example_ecdsa.py
-```
\ No newline at end of file
+```
+
+To run individual benchmarks and examples manually before
+installation add the build `src` directory to your system
+dynamic library path.
+
+e.g. for Linux
+
+```sh
+export LD_LIBRARY_PATH=<build_dir>/src/:$LD_LIBRARY_PATH
+```
diff --git a/python/CMakeLists.txt b/python/benchmark/CMakeLists.txt
similarity index 84%
copy from python/CMakeLists.txt
copy to python/benchmark/CMakeLists.txt
index d7ed21c..8a39633 100644
--- a/python/CMakeLists.txt
+++ b/python/benchmark/CMakeLists.txt
@@ -13,10 +13,5 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
-
-include(PythonSiteDirs)
-
-add_subdirectory(amcl)
-add_subdirectory(test)
-add_subdirectory(examples)
+file(GLOB BENCH *.py)
+file(COPY ${BENCH} DESTINATION "${PROJECT_BINARY_DIR}/python/benchmark")
diff --git a/python/benchmark/bench.py b/python/benchmark/bench.py
new file mode 100644
index 0000000..43ed625
--- /dev/null
+++ b/python/benchmark/bench.py
@@ -0,0 +1,62 @@
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+"""
+
+import time
+
+multipliers = {
+    "ms": 1000,
+    "us": 1000000
+}
+
+def time_func(stmt, fncall, minIter=10, minTime=1, unit="ms"):
+    """Benchmark a function
+
+    Benchmark fncall(). It iterates until minIter or minTime is reached.
+    The results are printed using the specified time unit
+
+    Args::
+
+        stmt    : name of the benchmarked function
+        fncall  : function call initialized with the functools partial
+        minIter : minimum number of iterations to run, regardless of time spent
+        minTime : minimum number of time to spend, regardless of iterations
+        unit    : "ms" or "us", the time unit for the benchmark
+
+    Returns::
+
+    Raises::
+        KeyError
+    """
+
+    unit_multiplier = multipliers[unit]
+
+    total_time = 0
+    nIter = 0
+
+    while nIter < minIter or total_time < minTime:
+        t = time.time()
+
+        fncall()
+
+        elapsed_time = time.time() - t
+        total_time = total_time + elapsed_time
+        nIter+=1
+
+    iter_time = (total_time * unit_multiplier) / nIter
+    print("func: {} \tnIter: {} \ttotal_time: {:.2f}s \titer_time: 
{:.2f}{}".format(stmt, nIter, total_time, iter_time, unit))
diff --git a/python/bench_mpc.py b/python/benchmark/bench_mta.py
similarity index 57%
rename from python/bench_mpc.py
rename to python/benchmark/bench_mta.py
index d246a1a..8ae292c 100755
--- a/python/bench_mpc.py
+++ b/python/benchmark/bench_mta.py
@@ -19,80 +19,37 @@ specific language governing permissions and limitations
 under the License.
 """
 
-import time
-import warnings
-from amcl import mpc
-
-warnings.filterwarnings("ignore")
-
-
-def time_func(stmt, fncall, n=10):
-    t = time.process_time()
-    for i in range(1,i):
-        fncall
-        total_time = time.process_time() - t
-        iter_time = total_time / n
-        iter_per_sec = n / total_time
-        print(f"func:{stmt} nIter:{n} total_time:{total_time} 
iter_time:{iter_time} iter_per_sec: {iter_per_sec}")
-
-
-nIter = 10
+from context import mpc
+from bench import time_func
 
 seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
 
 P_hex = 
"94f689d07ba20cf7c7ca7ccbed22ae6b40c426db74eaee4ce0ced2b6f52a5e136663f5f1ef379cdbb0c4fdd6e4074d6cff21082d4803d43d89e42fd8dfa82b135aa31a8844ffea25f255f956cbc1b9d8631d01baf1010d028a190b94ce40f3b72897e8196df19edf1ff62e6556f2701d52cef1442e3301db7608ecbdcca703db"
-
 Q_hex = 
"9a9ad73f246df853e129c589925fdad9df05606a61081e62e72be4fb33f6e5ec492cc734f28bfb71fbe2ba9a11e4c02e2c0d103a5cbb0a9d6402c07de63b1b995dd72ac8f29825d66923a088b421fb4d52b0b855d2f5dde2be9b0ca0cee6f7a94e5566735fe6cff1fcad3199602f88528d19aa8d0263adff8f5053c38254a2a3"
 
 a_hex = "0000000000000000000000000000000000000000000000000000000000000002"
-
 b_hex = "0000000000000000000000000000000000000000000000000000000000000003"
 
 if __name__ == "__main__":
-
     seed = bytes.fromhex(seed_hex)
     p = bytes.fromhex(P_hex)
     q = bytes.fromhex(Q_hex)
     a = bytes.fromhex(a_hex)
     b = bytes.fromhex(b_hex)
 
-    ai = int(a_hex, 16)
-    bi = int(b_hex, 16)
-    expected = ai * bi % mpc.curve_order
-
     # random number generator
     rng = mpc.create_csprng(seed)
 
+    # Generate quantities for benchmark
     paillier_pk, paillier_sk = mpc.paillier_key_pair(rng)
+    ca = mpc.mpc_mta_client1(rng, paillier_pk, a)
+    cb, beta = mpc.mpc_mta_server(rng, paillier_pk, b, ca)
+    alpha = mpc.mpc_mta_client2(paillier_sk, cb)
 
-    total_time=0
-    for i in range(1,nIter):
-        #t = time.process_time()
-        t = time.time()
-        ca = mpc.mpc_mta_client1(rng, paillier_pk, a)
-        # elapsed_time = time.process_time() - t
-        elapsed_time = time.time() - t
-        total_time = total_time + elapsed_time
-    iter_time = int ((total_time * 1000) / nIter)
-    print(f"mpc_mta_client1 iteractions: {nIter} total_time: {total_time} 
iter_time: {iter_time}")
-
-    total_time=0
-    for i in range(1,nIter):
-        t = time.time()
-        cb, beta = mpc.mpc_mta_server(rng, paillier_pk, b, ca)
-        elapsed_time = time.time() - t
-        total_time = total_time + elapsed_time
-    iter_time = int ((total_time * 1000) / nIter)
-    print(f"mpc_mta_server iteractions: {nIter} total_time: {total_time} 
iter_time: {iter_time}")
-
-    total_time=0
-    for i in range(1,nIter):
-        t = time.time()
-        alpha = mpc.mpc_mta_client2(paillier_sk, cb)
-        elapsed_time = time.time() - t
-        total_time = total_time + elapsed_time
-    iter_time = int ((total_time * 1000) / nIter)
-    print(f"mpc_mta_client2 iteractions: {nIter} total_time: {total_time} 
iter_time: {iter_time}")
+    # Check consistency of the generated quantities
+    ai = int(a_hex, 16)
+    bi = int(b_hex, 16)
+    expected = ai * bi % mpc.curve_order
 
     alphai = int(alpha.hex(), 16)
     betai = int(beta.hex(), 16)
@@ -100,5 +57,15 @@ if __name__ == "__main__":
 
     assert got == expected, f"expected {hex(expected)} got {hex(got)}"
 
+    # Run benchmark
+    fncall = lambda: mpc.mpc_mta_client1(rng, paillier_pk, a)
+    time_func("mpc_mta_client1", fncall)
+
+    fncall = lambda: mpc.mpc_mta_server(rng, paillier_pk, b, ca)
+    time_func("mpc_mta_server ", fncall)
+
+    fncall = lambda: mpc.mpc_mta_client2(paillier_sk, cb)
+    time_func("mpc_mta_client2", fncall)
+
     # Clear memory
     mpc.kill_csprng(rng)
diff --git a/python/benchmark/bench_schnorr.py 
b/python/benchmark/bench_schnorr.py
new file mode 100755
index 0000000..ab0d2af
--- /dev/null
+++ b/python/benchmark/bench_schnorr.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+"""
+
+from context import schnorr
+from bench import time_func
+
+r_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290"
+x_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3"
+V_hex = "032cf4b348c9d00718f01ed98923e164df53b5e8bc4c2250662ed2df784e1784f4"
+
+if __name__ == "__main__":
+    r = bytes.fromhex(r_hex)
+    x = bytes.fromhex(x_hex)
+    V = bytes.fromhex(V_hex)
+
+    # Generate quantities for benchmark
+    r, C = schnorr.commit(None, r)
+    e = schnorr.challenge(V, C)
+    p = schnorr.prove(r, e, x)
+
+    # Check consistency of the generated quantities
+    assert schnorr.verify(V, C, e, p) == schnorr.OK
+
+    # Run benchmark
+    fncall = lambda: schnorr.commit(None, r)
+    time_func("commit   ", fncall, unit="us")
+
+    fncall = lambda: schnorr.challenge(V, C)
+    time_func("challenge", fncall, unit="us")
+
+    fncall = lambda: schnorr.prove(r, e, x)
+    time_func("prove    ", fncall, unit="us")
+
+    fncall = lambda: schnorr.verify(V, C, e, p)
+    time_func("verify   ", fncall, unit="us")
diff --git a/python/benchmark/context.py b/python/benchmark/context.py
new file mode 100644
index 0000000..c7a9ac2
--- /dev/null
+++ b/python/benchmark/context.py
@@ -0,0 +1,25 @@
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+"""
+
+import os
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 
'..')))
+
+from amcl import mpc, schnorr

Reply via email to