diff --git a/client/src/router/index.js b/client/src/router/index.js index cd0f1dd..700ee14 100644 --- a/client/src/router/index.js +++ b/client/src/router/index.js @@ -5,6 +5,7 @@ import Client from "@/views/Client.vue" import Seller from "@/views/Seller.vue" import Delivery from "@/views/Delivery.vue" import Styles from "@/views/Styles.vue" +import Performance from "@/views/Performance.vue" const publicPath = process.env.NODE_ENV === 'production' ? '/tno-eats' : ''; @@ -56,6 +57,14 @@ const routes = [ meta: { title: 'Styles', }, + }, + { + path: `${publicPath}/performance`, + name: "Performance", + component: Performance, + meta: { + title: 'Performance', + }, } ] diff --git a/client/src/utils/crypto.js b/client/src/utils/crypto.js index cc27ea7..23fac7f 100644 --- a/client/src/utils/crypto.js +++ b/client/src/utils/crypto.js @@ -5,7 +5,7 @@ import { Buffer } from 'buffer'; // Using: https://github.com/dchest/tweetnacl-js/wiki/Examples const newNonce = () => randomBytes(box.nonceLength); -// const generateKeyPair = () => box.keyPair(); +const generateKeyPair = () => box.keyPair(); const generateKey = () => encodeBase64(randomBytes(secretbox.keyLength)); @@ -127,4 +127,4 @@ const isValidHash = async (clientAddress, saltString, hashedAddress) => { } } -export { encryptOrderInfo, decryptOrderInfo, decryptClientOrderInfo, isValidHash }; +export { encryptOrderInfo, decryptOrderInfo, decryptClientOrderInfo, isValidHash, generateKeyPair, generateKey }; diff --git a/client/src/utils/performance.js b/client/src/utils/performance.js new file mode 100644 index 0000000..521205a --- /dev/null +++ b/client/src/utils/performance.js @@ -0,0 +1,110 @@ +import { downloadDeliveryInfo, uploadDeliveryInfo } from '@/endpoints/ipfs'; +import { encryptOrderInfo, decryptOrderInfo, generateKeyPair, generateKey } from '@/utils/crypto'; +import { encodeBase64 } from 'tweetnacl-util'; + +const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +const measureOneRound = async (orderInfo) => { + const sellerKeys = generateKeyPair(); + const clientKeys = generateKeyPair(); + const clientKey = generateKey(); + + const sellerPublicKey = encodeBase64(sellerKeys.publicKey); + const sellerSecretKey = encodeBase64(sellerKeys.secretKey); + const clientPublicKey = encodeBase64(clientKeys.publicKey); + const clientSecretKey = encodeBase64(clientKeys.secretKey); + + performance.mark("start-encrypt"); + // Encrypt + const encrypted = await encryptOrderInfo(sellerPublicKey, clientPublicKey, clientSecretKey, clientKey, orderInfo); + performance.mark("end-encrypt"); + // Upload + const path = await uploadDeliveryInfo(encrypted); + performance.mark("end-upload"); + // Download + const downloadedInfo = await downloadDeliveryInfo(path); + performance.mark("end-download"); + // Decrypt + await decryptOrderInfo(downloadedInfo, sellerSecretKey); + performance.mark("end-decrypt"); + + performance.measure("total-encrypt", "start-encrypt", "end-encrypt"); + performance.measure("total-upload", "end-encrypt", "end-upload"); + performance.measure("total-download", "end-upload", "end-download"); + performance.measure("total-decrypt", "end-download", "end-decrypt"); + + const measurement = [ + performance.getEntriesByName('total-encrypt', 'measure').pop().duration, + performance.getEntriesByName('total-upload', 'measure').pop().duration, + performance.getEntriesByName('total-download', 'measure').pop().duration, + performance.getEntriesByName('total-decrypt', 'measure').pop().duration, + ]; + + // Clear all marks and measures for next run + performance.clearMarks('start-encrypt'); + performance.clearMarks('end-encrypt'); + performance.clearMarks('end-upload'); + performance.clearMarks('end-download'); + performance.clearMarks('end-decrypt'); + performance.clearMeasures('total-encrypt'); + performance.clearMeasures('total-upload'); + performance.clearMeasures('total-download'); + performance.clearMeasures('total-decrypt'); + + return measurement; +}; + +const measureBytes = async (orderInfo) => { + const sellerKeys = generateKeyPair(); + const clientKeys = generateKeyPair(); + const clientKey = generateKey(); + + const sellerPublicKey = encodeBase64(sellerKeys.publicKey); + const clientPublicKey = encodeBase64(clientKeys.publicKey); + const clientSecretKey = encodeBase64(clientKeys.secretKey); + + const encrypted = await encryptOrderInfo(sellerPublicKey, clientPublicKey, clientSecretKey, clientKey, orderInfo); + const byteSize = str => new Blob([str]).size; + console.log(`Items size: ${byteSize(JSON.stringify(orderInfo))}, IPFS size: ${byteSize(encrypted)}`); +}; + +const measurePerformance = async () => { + console.log('Starting the measurements'); + const measurements = {}; + for (const orderSize of [1, 5, 25, 100, 500]) { + console.log(`Measuring orderSize = ${orderSize}`); + measurements[orderSize] = []; + for (let i = 0; i < 10; ++i) { + try { + const orderInfo = { + "deliveryAddress": { + "street": "The Street Address", + "hnr": "1234", + "hnr_add": "AB", + "zip": "0000 AA" + }, + "cart": Array(orderSize).fill({ + "id": "cc919e21-ae5b-5e1f-d023-c4ach669520c", + "name": "TNO burger", + "img": "https://assets.biggreenegg.eu/app/uploads/2019/03/28145521/topimage-classic-hamburger-2019m04-800x534.jpg", + "price": 1000.50, + "quantity": 100 + }), + }; + const result = await measureOneRound(orderInfo); + measurements[orderSize].push(result); + console.log(result); + await sleep(5000); + await measureBytes(orderInfo); + } catch (_) { + console.log(_); // Too many requests + await sleep(10000); + } + } + } + + console.log('Results') + console.log(JSON.stringify(measurements, null, 2)); +}; + +export { measurePerformance }; diff --git a/client/src/views/Performance.vue b/client/src/views/Performance.vue new file mode 100644 index 0000000..70d08bd --- /dev/null +++ b/client/src/views/Performance.vue @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/measurements/.gitignore b/measurements/.gitignore new file mode 100644 index 0000000..6769e21 --- /dev/null +++ b/measurements/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/measurements/measurement.pdf b/measurements/measurement.pdf new file mode 100644 index 0000000..346f6ac Binary files /dev/null and b/measurements/measurement.pdf differ diff --git a/measurements/plot.py b/measurements/plot.py new file mode 100644 index 0000000..d96dce7 --- /dev/null +++ b/measurements/plot.py @@ -0,0 +1,54 @@ +from statistics import mean, stdev +import matplotlib.pyplot as plt +import numpy as np +import json + + +def _get(data, index): + # Maps the array of measurements into single values depending on index + return [[xs[index] for xs in xss] for xss in data.values()] + + +def _mean(data, index): + return [mean(values) for values in _get(data, index)] + + +def _stdev(data, index): + return [stdev(values) for values in _get(data, index)] + + +with open('result.json', 'r') as f: + data = json.load(f) + + +labels = data.keys() + +enc_means = _mean(data, 0) +enc_std = _stdev(data, 0) + +upload_means = _mean(data, 1) +upload_std = _stdev(data, 1) + +download_means = _mean(data, 2) +download_std = _stdev(data, 2) + +dec_means = _mean(data, 3) +dec_std = _stdev(data, 3) + +width = 0.25 + +markers = np.arange(1,6) + +fig, ax = plt.subplots() +ax.bar([int(x) - 0.125 for x in markers], enc_means, width, yerr=enc_std, capsize=4, label='Encrypt') +ax.bar([int(x) - 0.125 for x in markers], upload_means, width, yerr=upload_std, bottom=enc_means, capsize=4, label='Upload') +ax.bar([int(x) + 0.125 for x in markers], download_means, width, yerr=download_std, capsize=4, label='Download') +ax.bar([int(x) + 0.125 for x in markers], dec_means, width, yerr=dec_std, bottom=download_means, capsize=4, label='Decrypt') + +ax.set_ylabel('Milliseconds') +ax.set_title('Performance of Crypto and IPFS') +ax.set_xticks(markers) +ax.set_xticklabels(labels) +ax.legend() + +plt.savefig("measurement.pdf", bbox_inches="tight") diff --git a/measurements/result.json b/measurements/result.json new file mode 100644 index 0000000..0481346 --- /dev/null +++ b/measurements/result.json @@ -0,0 +1,312 @@ +{ + "1": [ + [ + 6.200000002980232, + 301.29999999701977, + 1229.2000000029802, + 10.100000001490116 + ], + [ + 11.299999997019768, + 325.5, + 1018.6000000014901, + 8.5 + ], + [ + 3.2999999970197678, + 305.40000000596046, + 846.5, + 9.199999995529652 + ], + [ + 12.199999995529652, + 275.1000000014901, + 1049.3999999985099, + 10.100000001490116 + ], + [ + 10.200000002980232, + 325.09999999403954, + 1132.7000000029802, + 7 + ], + [ + 9.399999998509884, + 297.8999999985099, + 1143.7000000029802, + 7.0999999940395355 + ], + [ + 12.5, + 472.3999999985099, + 1131.3999999985099, + 7.200000002980232 + ], + [ + 8.900000005960464, + 353.59999999403954, + 972.4000000059605, + 7.0999999940395355 + ], + [ + 7.600000001490116, + 311.30000000447035, + 1105.3999999985099, + 6.199999995529652 + ], + [ + 7.399999998509884, + 1320.7000000029802, + 918.6000000014901, + 6.699999995529652 + ] + ], + "5": [ + [ + 10.600000001490116, + 308.29999999701977, + 874.3999999985099, + 7.700000002980232 + ], + [ + 6.5, + 338.8999999985099, + 996, + 7.399999998509884 + ], + [ + 9, + 254.5, + 873.7000000029802, + 1.5999999940395355 + ], + [ + 6.899999998509884, + 324.90000000596046, + 936.3999999985099, + 7.299999997019768 + ], + [ + 6.5, + 291, + 917.8999999985099, + 7.600000001490116 + ], + [ + 6.700000002980232, + 363.6000000014901, + 959, + 6.299999997019768 + ], + [ + 7.200000002980232, + 280.79999999701977, + 1137.1000000014901, + 7.100000001490116 + ], + [ + 7.200000002980232, + 330.5, + 1091.6000000014901, + 9.199999995529652 + ], + [ + 6.5, + 317.1000000014901, + 1105, + 7 + ], + [ + 6.899999998509884, + 321.19999999552965, + 891.7000000029802, + 7.5 + ] + ], + "25": [ + [ + 12.099999994039536, + 494, + 1037, + 10 + ], + [ + 13, + 538.7999999970198, + 1188.8000000044703, + 9.299999997019768 + ], + [ + 11.5, + 695, + 987.2999999970198, + 10.600000001490116 + ], + [ + 11.800000004470348, + 445.29999999701977, + 1005.1000000014901, + 9.600000001490116 + ], + [ + 13.799999997019768, + 1087.2000000029802, + 1147.8999999985099, + 10.200000002980232 + ], + [ + 11.399999998509884, + 678.1999999955297, + 1141.9000000059605, + 3.399999998509884 + ], + [ + 11.199999995529652, + 565.3000000044703, + 1275.1999999955297, + 8.700000002980232 + ], + [ + 14.899999998509884, + 513.1999999955297, + 1108, + 10.5 + ], + [ + 4.600000001490116, + 643.3999999985099, + 987.1000000014901, + 7.800000004470348 + ], + [ + 10.899999998509884, + 472.70000000298023, + 951.3999999985099, + 7.299999997019768 + ] + ], + "100": [ + [ + 14.399999998509884, + 710.3999999985099, + 1376.3999999985099, + 16.400000005960464 + ], + [ + 10.900000005960464, + 848.5999999940395, + 1942, + 17.80000000447035 + ], + [ + 11.199999995529652, + 804.8000000044703, + 1749.2999999970198, + 16.5 + ], + [ + 25.299999997019768, + 681.2000000029802, + 1434, + 18.899999998509884 + ], + [ + 25, + 598.7000000029802, + 1909.3999999985099, + 18.69999999552965 + ], + [ + 23.5, + 888.1000000014901, + 931.8000000044703, + 17 + ], + [ + 24.80000000447035, + 772.5999999940395, + 1741.7000000029802, + 8.299999997019768 + ], + [ + 23.299999997019768, + 636.9000000059605, + 2097.5999999940395, + 17 + ], + [ + 23.899999998509884, + 662.3999999985099, + 1965.3000000044703, + 8.299999997019768 + ], + [ + 10.100000001490116, + 611.3999999985099, + 1850.8999999985099, + 14.600000001490116 + ] + ], + "500": [ + [ + 52.399999998509884, + 1058.1000000014901, + 2008.6000000014901, + 47.399999998509884 + ], + [ + 53.899999998509884, + 1271.5, + 2675, + 39.899999998509884 + ], + [ + 31.200000002980232, + 1472.3999999985099, + 2020.3000000044703, + 24.099999994039536 + ], + [ + 50.099999994039536, + 1069.5, + 2268.8000000044703, + 29.299999997019768 + ], + [ + 42.899999998509884, + 1163.2999999970198, + 2177.7000000029802, + 42.5 + ], + [ + 56.29999999701977, + 2244, + 2617.39999999851, + 37.600000001490116 + ], + [ + 51.20000000298023, + 991.8999999985099, + 2475, + 40.399999998509884 + ], + [ + 50.70000000298023, + 951, + 2332.2000000029802, + 42.399999998509884 + ], + [ + 48.29999999701977, + 930.2000000029802, + 2573, + 42 + ], + [ + 52.29999999701977, + 1132.1000000014901, + 2058.60000000149, + 37.19999999552965 + ] + ] +}