Last active
October 27, 2023 01:51
-
-
Save bergkvist/186b15ec2b7e9cb04f7835973ae98371 to your computer and use it in GitHub Desktop.
Fireblocks MPC compiled to wasm32-wasi using zig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# How to use: | |
# 1. Make sure you have nix installed (https://nix.dev/install-nix) | |
# 2. Download this file, and name it for example `fireblocks-mpc-lib-wasm32-wasi.nix` | |
# 3. Run `nix-shell fireblocks-mpc-lib-wasm32-wasi.nix`. | |
# 4. Run `wasitest` inside the nix-shell environment to run the paillier benchmark. | |
{ pkgs ? import (builtins.fetchTarball { | |
url = "https://github.com/NixOS/nixpkgs/archive/51d906d2341c9e866e48c2efcaac0f2d70bfd43e.tar.gz"; | |
sha256 = "16nmvxfiyna5y9gwd2i3bhkpbn0nn37i481g53zc0ycw67k268sv"; | |
}) {} | |
, openssl-src ? (builtins.fetchTarball { | |
url = "https://github.com/openssl/openssl/archive/e3d897d3fa3b48bb835fab0665a435469beea7ae.tar.gz"; | |
sha256 = "128py0kpvg5waadgp575lnbm2jfbjp685xx1i2bap2bwap0h68vs"; | |
}) | |
, openssl-wasm-src ? (builtins.fetchTarball { | |
url = "https://github.com/jedisct1/openssl-wasm/archive/72ca3f2c90777bf860801e11da75219d11e9b4d7.tar.gz"; | |
sha256 = "10jx2fdmy2x2il0g0m9wp08g62lkxvfa5i042pjrhqhc3hbfavwp"; | |
}) | |
, fireblocks-mpc-lib-src ? (builtins.fetchTarball { | |
url = "https://github.com/fireblocks/mpc-lib/archive/84b7fb83502a998703b6ceb113273fc20fa55b7b.tar.gz"; | |
sha256 = "13inkl865dcxhib68zyl3ghfzcqlwhhza647v92cxhw5dnm0537n"; | |
}) | |
}: | |
let | |
paillier-benchmark-cpp = pkgs.writeText "paillier-benchmark.cpp" '' | |
#include <iostream> | |
#include "crypto/paillier/paillier.h" | |
using Clock = std::conditional<std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock>::type; | |
int main() { | |
auto before = Clock::now(); | |
paillier_public_key_t* paillier_pub = NULL; | |
paillier_private_key_t* paillier_priv = NULL; | |
long paillier_res = paillier_generate_key_pair(2048, &paillier_pub, &paillier_priv); | |
if (paillier_res != PAILLIER_SUCCESS) { | |
std::cout << "Failed to generate paillier keypair\n"; | |
} else { | |
std::cout << "Successfully generated paillier keypair\n"; | |
} | |
auto after = Clock::now(); | |
std::cout << "Time passed: " << std::chrono::duration_cast<std::chrono::milliseconds>(after - before).count() << " ms\n"; | |
} | |
''; | |
openssl-wasm = pkgs.runCommand "openssl-wasm" { | |
src = openssl-src; | |
patches = "${openssl-wasm-src}/patches"; | |
buildInputs = [ pkgs.zig pkgs.perl ]; | |
FEATURE_FLAGS = "no-asm no-async no-egd no-ktls no-module no-posix-io no-secure-memory no-shared no-sock no-stdio no-thread-pool no-threads no-ui-console no-weak-ssl-ciphers"; | |
AR = "zig ar"; | |
RANLIB = "zig ranlib"; | |
CC = "zig cc --target=wasm32-wasi"; | |
CFLAGS = "-Ofast -Werror -Qunused-arguments -Wno-shift-count-overflow"; | |
CPPFLAGS = "-D_WASI_EMULATED_GETPID -Dgetuid=getpagesize -Dgeteuid=getpagesize -Dgetgid=getpagesize -Dgetegid=getpagesize"; | |
CXXFLAGS = "-Werror -Qunused-arguments -Wno-shift-count-overflow"; | |
LDFLAGS = "-s -lwasi-emulated-getpid"; | |
XDG_CACHE_HOME = ".cache"; | |
CROSS_COMPILE = ""; | |
} '' | |
cp -r $src/* . | |
chmod -R u+rwx . | |
for patch in "$patches"/*.patch; do | |
patch -p1 < "$patch" | |
done | |
perl Configure --banner="wasm32-wasi port" $FEATURE_FLAGS wasm32-wasi || exit 1 | |
make "-j$NIX_BUILD_CORES" | |
mkdir -p $out/lib $out/include | |
mv *.a $out/lib | |
cp -r include/openssl $out/include | |
''; | |
fireblocks-mpc-wasm-objects = pkgs.runCommand "fireblocks-mpc-wasm-objects" { | |
src = "${fireblocks-mpc-lib-src}/src"; | |
include = "${fireblocks-mpc-lib-src}/include"; | |
buildInputs = [ pkgs.zig ]; | |
XDG_CACHE_HOME = ".cache"; | |
CROSS_COMPILE = ""; | |
} '' | |
log() { IFS=' ' printf '\n%s\n' "$*"; eval "$@"; } | |
mkdir -p $out | |
cp -r $src/* $out | |
chmod -R u+rw $out | |
for cfile in $(find $out/common -name "*.c" | sort | grep -v curve25519.c); do | |
log zig cc --target=wasm32-wasi -Ofast -c -Wno-deprecated -I$include -I${openssl-wasm}/include $cfile -o $cfile.o | |
done | |
for cppfile in $(find $out/common -name "*.cpp" | sort | grep -v asymmetric_eddsa_cosigner_server.cpp | grep -v cmp_ecdsa_online_signing_service.cpp | grep -v eddsa_online_signing_service.cpp); do | |
log zig c++ --target=wasm32-wasi -Ofast -c -Wno-deprecated -Wno-format -I$include -I${openssl-wasm}/include $cppfile -o $cppfile.o | |
done | |
''; | |
fireblocks-mpc-lib = pkgs.runCommand "fireblocks-mpc-lib" { | |
objects = fireblocks-mpc-wasm-objects; | |
include = "${fireblocks-mpc-lib-src}/include"; | |
buildInputs = [ pkgs.zig pkgs.binaryen ]; | |
XDG_CACHE_HOME = ".cache"; | |
CROSS_COMPILE = ""; | |
} '' | |
log() { IFS=' ' printf '\n%s\n' "$*"; eval "$@"; } | |
mkdir -p $out/lib | |
objs=$(find $objects/common -name "*.o" | sort | paste -sd' ' -) | |
log zig c++ --target=wasm32-wasi -Ofast -s -lwasi-emulated-getpid -I$include ${paillier-benchmark-cpp} ${openssl-wasm}/lib/libcrypto.a $objs -o $out/lib/mpc.wasm | |
log wasm-opt -O3 -o $out/lib/mpc.wasm $out/lib/mpc.wasm | |
''; | |
nodejs-wasi-test = pkgs.writeText "wasitest.js" '' | |
const fs = require('fs') | |
const { WASI } = require('wasi') | |
main() | |
async function main() { | |
const wasi = new WASI({ version: 'preview1' }) | |
const { instance } = await WebAssembly.instantiate( | |
fs.readFileSync('${fireblocks-mpc-lib}/lib/mpc.wasm'), | |
wasi.getImportObject() | |
) | |
wasi.start(instance) | |
} | |
''; | |
in pkgs.mkShell { | |
mpclib = fireblocks-mpc-lib; | |
buildInputs = [ | |
(pkgs.writeShellScriptBin "wasitest" '' | |
echo "test.js: ${nodejs-wasi-test}" | |
echo "main.cpp: ${paillier-benchmark-cpp}" | |
echo "mpc.wasm: ${fireblocks-mpc-lib}/lib/mpc.wasm" | |
echo "---" | |
echo "Running wasm32-wasi test..." | |
NODE_NO_WARNINGS=1 ${pkgs.nodejs_21}/bin/node ${nodejs-wasi-test} | |
'') | |
]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment