Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ABY3 #82

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/test-aby3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Build and test the Docker container for ABY3

on:
push:
branches: [ master ]
paths:
- aby3/*
pull_request:
branches: [ master ]
paths:
- aby3/*

jobs:
build:
name: Build container for ABY3
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3
- uses: docker/setup-buildx-action@v2
- uses: docker/build-push-action@v4
with:
context: aby3
tags: aby3
load: true
cache-from: type=gha
cache-to: type=gha,mode=max
push: false
50 changes: 50 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
}
}
18 changes: 18 additions & 0 deletions aby3/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM ubuntu:22.04

WORKDIR /root

RUN apt update \
&& apt install -y vim git build-essential python3 cmake

ADD install.sh .
RUN ./install.sh

WORKDIR /root/aby3
ADD source ./samples
# build our examples
RUN python3 build.py

ADD run_example.sh .

ENTRYPOINT ./run_example.sh xtabs
7 changes: 7 additions & 0 deletions aby3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ABY^3 was developed by Peter Rindal.

Currently fails to build with error
```
error: no matching function for call to 'osuCrypto::Channel::asyncSend(unsigned char*&, long unsigned int&, osuCrypto::OblvPermutation::send(osuCrypto::Channel&, osuCrypto::Channel&, osuCrypto::Matrix<unsigned char>, std::__cxx11::string)::<lambda()>)'
recvrChl.asyncSend(data, size, [a = std::move(src)](){});
```
12 changes: 12 additions & 0 deletions aby3/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

set -ex

git clone https://github.com/ladnir/aby3.git
cd aby3/
git checkout 854ca1b
python3 build.py --setup
python3 build.py

mkdir samples
printf "add_subdirectory(samples)\n" >> CMakeLists.txt
16 changes: 16 additions & 0 deletions aby3/run_example.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh

set -ex

SAMPLE=$1

BIN=out/build/linux/samples/samples.exe

if [ $SAMPLE = mult3 -o $SAMPLE = innerprod -o $SAMPLE = xtabs ]; then
$BIN -p 0 -u $SAMPLE &
$BIN -p 1 -u $SAMPLE &
$BIN -p 2 -u $SAMPLE
else
echo "Bad sample name. Supported samples: mult3, innerprod, xtabs"
exit 1
fi
17 changes: 17 additions & 0 deletions aby3/source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

#project(samples)

#############################################
# Build samples.exe #
#############################################

file(GLOB_RECURSE SRC_SAMPLES ${CMAKE_SOURCE_DIR}/samples/*.cpp)
include_directories(${CMAKE_SOURCE_DIR}/samples/)

add_executable(samples.exe ${SRC_SAMPLES})

target_link_libraries(samples.exe com-psi)
target_link_libraries(samples.exe aby3-ML)
target_link_libraries(samples.exe com-psi_Tests)
target_link_libraries(samples.exe aby3_Tests)
target_link_libraries(samples.exe oc::tests_cryptoTools)
68 changes: 68 additions & 0 deletions aby3/source/innerprod.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <iostream>
#include <cryptoTools/Network/IOService.h>

#include "aby3/sh3/Sh3Runtime.h"
#include "aby3/sh3/Sh3Encryptor.h"
#include "aby3/sh3/Sh3Evaluator.h"

#include "innerprod.h"

using namespace oc;
using namespace aby3;

void innerprod_test(oc::u64 partyIdx, std::vector<int> values)
{
if (partyIdx == 0)
std::cout << "testing innerprod..." << std::endl;

IOService ios;
Sh3Encryptor enc;
Sh3Evaluator eval;
Sh3Runtime runtime;
setup_samples(partyIdx, ios, enc, eval, runtime);

// encrypt (only parties 0,1 provide input)
u64 rows = values.size();
std::vector<si64> A(rows);
std::vector<si64> B(rows);

// note: this fails if you try to make multiple local/remote calls in the same if/else statement
// maybe could fix this with tasks?
for (int i = 0; i < 10; i++)
{
if (partyIdx == 0)
{
enc.localInt(runtime, values[i], A[i]).get();
}
else
{
enc.remoteInt(runtime, A[i]).get();
}

if (partyIdx == 1)
{
enc.localInt(runtime, values[i], B[i]).get();
}
else
{
enc.remoteInt(runtime, B[i]).get();
}
}

// parallel multiplications
std::vector<si64> prods(rows);
Sh3Task task = runtime.noDependencies();
for (u64 i = 0; i < rows; ++i)
task = eval.asyncMul(task, B[i], A[i], prods[i]);
task.get();

// addition
si64 sum = prods[0];
for (u64 i = 1; i < rows; ++i)
sum = sum + (si64)prods[i];

// reveal result
i64 result;
enc.revealAll(runtime, sum, result).get();
std::cout << "result: " << result << std::endl;
}
14 changes: 14 additions & 0 deletions aby3/source/innerprod.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once
#include <cryptoTools/Common/CLP.h>
void innerprod_test(oc::u64 partyIdx, std::vector<int> values);

#include <cryptoTools/Network/IOService.h>
#include "aby3/sh3/Sh3Runtime.h"
#include "aby3/sh3/Sh3Encryptor.h"
#include "aby3/sh3/Sh3Evaluator.h"
void setup_samples(
aby3::u64 partyIdx,
oc::IOService &ios,
aby3::Sh3Encryptor &enc,
aby3::Sh3Evaluator &eval,
aby3::Sh3Runtime &runtime);
141 changes: 141 additions & 0 deletions aby3/source/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "mult3.h"
#include "innerprod.h"
#include "xtabs.h"

// testing and command line parsing
#include <tests_cryptoTools/UnitTests.h>
#include <cryptoTools/Common/CLP.h>
std::vector<std::string> unitTestTag{"u", "unitTest"};
std::vector<std::string> playerTag{"p", "player"};

// convenience function
#include <cryptoTools/Network/IOService.h>
#include "aby3/sh3/Sh3Runtime.h"
#include "aby3/sh3/Sh3Encryptor.h"
#include "aby3/sh3/Sh3Evaluator.h"

// This function sets up the basic classes that we will
// use to perform some computation. This mostly consists
// of creating Channels (network sockets) to the other
// parties and then establishing some shared randomness.
void setup_samples(
aby3::u64 partyIdx,
oc::IOService &ios,
aby3::Sh3Encryptor &enc,
aby3::Sh3Evaluator &eval,
aby3::Sh3Runtime &runtime);

void help()
{
std::cout << "-u ~~ to run all tests" << std::endl;
std::cout << "-u n1 [n2 ...] ~~ to run test n1, n2, ..." << std::endl;
std::cout << "-u -list ~~ to list all tests" << std::endl;

std::cout << "-p party ~~ indicate which party you are" << std::endl;
}

int main(int argc, char **argv)
{
try
{

oc::CLP cmd(argc, argv);

oc::u64 player;
if (cmd.isSet(playerTag))
{
player = cmd.getOr(playerTag, -1);
}
else
{
std::cout << "You need to specify which party you are" << std::endl;
return 0;
}

// this calls the appropriate test function based on command-line arg
// functions are defined in their respective .h files
if (cmd.isSet(unitTestTag))
{
std::string none = "";
if (cmd.getOr(unitTestTag, none).compare("mult3") == 0)
{
// hardcoded input value. expected result: 3*4*5 = 60
int value = 3 + player;
mult3_test(player, value);
}
if (cmd.getOr(unitTestTag, none).compare("innerprod") == 0)
{
std::vector<int> values(10);
// expected result: (0*0) + (1*2) + (2*4) + ... = 570
for (uint i = 0; i < values.size(); i++)
{
values[i] = (player + 1) * i;
}
innerprod_test(player, values);
}
if (cmd.getOr(unitTestTag, none).compare("xtabs") == 0)
{
std::vector<int> ids{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> values{0, 2, 2, 3, 4, 5, 6, 7, 8, 9};
xtabs_test(player, ids, values, 10);
}

return 0;
}

help();
}
catch (std::exception &e)
{
std::cout << e.what() << std::endl;
}

return 0;
}

using namespace aby3;
using namespace oc;
using namespace aby3;
using namespace oc;
void setup_samples(
aby3::u64 partyIdx,
oc::IOService &ios,
aby3::Sh3Encryptor &enc,
aby3::Sh3Evaluator &eval,
aby3::Sh3Runtime &runtime)
{
// A CommPkg is a pair of Channels (network sockets) to the other parties.
// See cryptoTools\frontend_cryptoTools\Tutorials\Network.cpp
// for details.
// since we're running them all locally, they're sitting on 3 different ports.
aby3::CommPkg comm;
switch (partyIdx)
{
case 0:
comm.mNext = oc::Session(ios, "127.0.0.1:1313", oc::SessionMode::Server, "01").addChannel();
comm.mPrev = oc::Session(ios, "127.0.0.1:1314", oc::SessionMode::Server, "02").addChannel();
break;
case 1:
comm.mNext = oc::Session(ios, "127.0.0.1:1315", oc::SessionMode::Server, "12").addChannel();
comm.mPrev = oc::Session(ios, "127.0.0.1:1313", oc::SessionMode::Client, "01").addChannel();
break;
default:
comm.mNext = oc::Session(ios, "127.0.0.1:1314", oc::SessionMode::Client, "02").addChannel();
comm.mPrev = oc::Session(ios, "127.0.0.1:1315", oc::SessionMode::Client, "12").addChannel();
break;
}

// in a real work example, where parties
// have different IPs, you have to give the
// Clients the IP of the server and you give
// the servers their own IP (to listen to).

// Establishes some shared randomness needed for the later protocols
enc.init(partyIdx, comm, sysRandomSeed());

// Establishes some shared randomness needed for the later protocols
eval.init(partyIdx, comm, sysRandomSeed());

// Copies the Channels and will use them for later protcols.
runtime.init(partyIdx, comm);
}
Loading
Loading