Skip to content

Commit

Permalink
Merge pull request #40 from pacu/dkg-support
Browse files Browse the repository at this point in the history
Dkg support
  • Loading branch information
pacu authored Jun 13, 2024
2 parents 9ab1346 + 85d6248 commit 98736ce
Show file tree
Hide file tree
Showing 16 changed files with 1,774 additions and 77 deletions.
554 changes: 552 additions & 2 deletions FrostSwift/Sources/FrostSwiftFFI/frost_uniffi_sdk.swift

Large diffs are not rendered by default.

14 changes: 1 addition & 13 deletions Scripts/build_go.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
#!/bin/bash
#!/bin/sh


if [[ "$OSTYPE" == "darwin"* ]]; then
ARCH=$(arch)

if [[ "$ARCH" == "arm64" ]]; then
cargo build --package frost-uniffi-sdk --package uniffi-bindgen --target aarch64-apple-darwin
else
cargo build --package frost-uniffi-sdk --package uniffi-bindgen --target x86_64-apple-darwin
fi

else
cargo build --package frost-uniffi-sdk --package uniffi-bindgen
fi
18 changes: 2 additions & 16 deletions Scripts/build_go_bindings.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
#!/bin/bash

ls target
#!/bin/sh

cargo install uniffi-bindgen-go --git https://github.com/NordSecurity/uniffi-bindgen-go --tag v0.2.1+v0.25.0


if [[ "$OSTYPE" == "darwin"* ]]; then
ARCH=$(arch)

if [[ "$ARCH" == "arm64" ]]; then
uniffi-bindgen-go --library './target/aarch64-apple-darwin/debug/libfrost_uniffi_sdk.dylib' --out-dir .
else
uniffi-bindgen-go --library './target/x86_64-apple-darwin/debug/libfrost_uniffi_sdk.dylib' --out-dir .
fi

else
uniffi-bindgen-go --library './target/debug/libfrost_uniffi_sdk.dylib' --out-dir .
fi
uniffi-bindgen-go --library './target/debug/libfrost_uniffi_sdk.dylib' --out-dir .
11 changes: 10 additions & 1 deletion Scripts/replace_remote_binary_with_local.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
#!/bin/sh
sed -i 's|^[[:space:]]*\.binaryTarget(name: "RustFramework", url: "https://github.com/pacu/frost-uniffi-sdk/releases/download/[^"]+/RustFramework.xcframework.zip", checksum: "[^"]+"\),| .binaryTarget(name: "RustFramework", path: "FrostSwift/RustFramework.xcframework.zip"),|' Package.swift

if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's|^[[:space:]]*\.binaryTarget(name: "RustFramework", url: "[^"]*", checksum: "[^"]*")\,| .binaryTarget(name: "RustFramework", path: "FrostSwift/RustFramework.xcframework.zip"),|' Package.swift

else
sed -i 's|^[[:space:]]*\.binaryTarget(name: "RustFramework", url: "[^"]*", checksum: "[^"]*")\,| .binaryTarget(name: "RustFramework", path: "FrostSwift/RustFramework.xcframework.zip"),|' Package.swift

fi


15 changes: 0 additions & 15 deletions Scripts/test_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,7 @@
ROOT_DIR=$(pwd)
SCRIPT_DIR="${SCRIPT_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )}"



if [[ "$OSTYPE" == "darwin"* ]]; then
ARCH=$(arch)

if [[ "$ARCH" == "arm64" ]]; then
TARGET="aarch64-apple-darwin"
else
TARGET="x86_64-apple-darwin"
fi


BINARIES_DIR="$ROOT_DIR/target/$TARGET/debug"
else
BINARIES_DIR="$ROOT_DIR/target/debug"
fi

BINDINGS_DIR="$ROOT_DIR/frost_go_ffi"

Expand Down
232 changes: 232 additions & 0 deletions frost-uniffi-sdk/src/dkg/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
use frost::{
keys::dkg::{
part1, part2, part3,
round1::{Package, SecretPackage},
round2,
},
Error, Identifier,
};
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
use rand::thread_rng;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
use uniffi;

use crate::{FrostError, FrostKeyPackage, FrostPublicKeyPackage, ParticipantIdentifier};

#[derive(uniffi::Record)]
pub struct DKGPart3Result {
pub public_key_package: FrostPublicKeyPackage,
pub key_package: FrostKeyPackage,
}

#[derive(uniffi::Object, Clone)]
pub struct DKGPart2Result {
pub secret: DKGRound2SecretPackage,
pub packages: Vec<DKGRound2Package>,
}

#[derive(uniffi::Record, Clone)]
pub struct DKGRound2Package {
// to whom this should be send to
pub identifier: ParticipantIdentifier,
// wrapped data
pub data: Vec<u8>,
}

impl DKGRound2Package {
fn from_package(
identifier: ParticipantIdentifier,
package: round2::Package,
) -> Result<DKGRound2Package, Error> {
Ok(DKGRound2Package {
identifier: identifier,
data: package.serialize()?,
})
}

fn into_package(&self) -> Result<round2::Package, Error> {
Ok(round2::Package::deserialize(&self.data)?)
}
}

#[derive(uniffi::Object)]
pub struct DKGPart1Result {
pub secret: DKGRound1SecretPackage,
pub package: DKGRound1Package,
}

#[derive(uniffi::Object, Clone)]
pub struct DKGRound2SecretPackage {
data: round2::SecretPackage,
}

#[derive(uniffi::Object, Clone)]
pub struct DKGRound1SecretPackage {
data: SecretPackage,
}

impl DKGRound1SecretPackage {
fn from_secret_package(secret_package: SecretPackage) -> DKGRound1SecretPackage {
DKGRound1SecretPackage {
data: secret_package,
}
}
}

#[derive(uniffi::Record, Clone)]
pub struct DKGRound1Package {
pub identifier: ParticipantIdentifier,
pub data: Vec<u8>,
}

impl DKGRound1Package {
fn into_package(&self) -> Result<Package, Error> {
Ok(Package::deserialize(&self.data)?)
}

fn from_package(
identifier: ParticipantIdentifier,
package: Package,
) -> Result<DKGRound1Package, Error> {
Ok(DKGRound1Package {
identifier: identifier,
data: package.serialize()?,
})
}
}

#[uniffi::export]
pub fn part_1(
participant_identifier: ParticipantIdentifier,
max_signers: u16,
min_signers: u16,
) -> Result<Arc<DKGPart1Result>, FrostError> {
let identifier = participant_identifier
.into_identifier()
.map_err(|_| FrostError::UnknownIdentifier)?;
let rng = thread_rng();
let part_one = part1(identifier, max_signers, min_signers, rng)
.map_err(|_| FrostError::InvalidConfiguration)?;

let secret = DKGRound1SecretPackage::from_secret_package(part_one.0);
let package = DKGRound1Package::from_package(participant_identifier, part_one.1)
.map_err(|_| FrostError::DeserializationError)?;

Ok(Arc::new(DKGPart1Result {
secret: secret,
package: package,
}))
}
/// DKG Part 2
/// receives a SecretPackage from round one generated by the same
/// participant and kept in-memory (and secretly) until now.
/// It also receives the round 1 packages corresponding to all the
/// other participants **except** itself.
///
/// Example: if P1, P2 and P3 are doing DKG, then when P1 runs part_2
/// this will receive a secret generated by P1 in part_1 and the
/// round 1 packages from P2 and P3. Everyone else has to do the same.
///
/// For part_3 the P1 will send the round 2 packages generated here to
/// the other participants P2 and P3 and should receive packages from
/// P2 and P3.
#[uniffi::export]
pub fn part_2(
secret_package: Arc<DKGRound1SecretPackage>,
round1_packages: HashMap<ParticipantIdentifier, DKGRound1Package>,
) -> Result<Arc<DKGPart2Result>, FrostError> {
let secret_package = secret_package.data.clone();

let mut packages: BTreeMap<Identifier, Package> = BTreeMap::new();

for (id, pkg) in round1_packages.into_iter() {
let package = pkg
.into_package()
.map_err(|_| FrostError::DeserializationError)?;
let identifier = id
.into_identifier()
.map_err(|_| FrostError::DeserializationError)?;
packages.insert(identifier, package);
}

let (secret, round2_packages) = part2(secret_package, &packages).map_err(|e| match e {
Error::IncorrectNumberOfCommitments => FrostError::DKGPart2IncorrectNumberOfCommitments,
Error::IncorrectNumberOfPackages => FrostError::DKGPart2IncorrectNumberOfPackages,
_ => FrostError::UnexpectedError,
})?;

let mut packages: Vec<DKGRound2Package> = Vec::new();

let secret = DKGRound2SecretPackage { data: secret };

for pkg in round2_packages.into_iter() {
let identifier = ParticipantIdentifier::from_identifier(pkg.0)
.map_err(|_| FrostError::SerializationError)?;

let package = DKGRound2Package::from_package(identifier.clone(), pkg.1)
.map_err(|_| FrostError::SerializationError)?;

packages.push(package);
}

Ok(Arc::new(DKGPart2Result {
secret: secret,
packages: packages,
}))
}

#[uniffi::export]
pub fn part_3(
secret_package: Arc<DKGRound2SecretPackage>,
round1_packages: HashMap<ParticipantIdentifier, DKGRound1Package>,
round2_packages: HashMap<ParticipantIdentifier, DKGRound2Package>,
) -> Result<DKGPart3Result, FrostError> {
let secret_package = secret_package.data.clone();

let mut round1_pkg: BTreeMap<Identifier, Package> = BTreeMap::new();

for (id, pkg) in round1_packages.into_iter() {
let package = pkg
.into_package()
.map_err(|_| FrostError::DeserializationError)?;
let identifier = id
.into_identifier()
.map_err(|_| FrostError::DeserializationError)?;
round1_pkg.insert(identifier, package);
}

let mut round2_pkg: BTreeMap<Identifier, round2::Package> = BTreeMap::new();

for (id, pkg) in round2_packages.into_iter() {
let package = pkg
.into_package()
.map_err(|_| FrostError::DeserializationError)?;
let identifier = id
.into_identifier()
.map_err(|_| FrostError::DeserializationError)?;
round2_pkg.insert(identifier, package);
}

let (key_packages, pubkey) = part3(&secret_package, &round1_pkg, &round2_pkg)
.map_err(|e| {
match e {
Error::IncorrectNumberOfPackages => FrostError::DKGPart3IncorrectNumberOfPackages,
Error::IncorrectPackage => FrostError::DKGPart3IncorrectRound1Packages,
Error::PackageNotFound => FrostError::DKGPart3PackageSendersMismatch,
_ => FrostError::UnexpectedError
}
})?;

Ok(DKGPart3Result {
public_key_package: FrostPublicKeyPackage::from_public_key_package(pubkey)
.map_err(|_| FrostError::SerializationError)?,
key_package: FrostKeyPackage::from_key_package(&key_packages)
.map_err(|_| FrostError::SerializationError)?,
})
}
1 change: 1 addition & 0 deletions frost-uniffi-sdk/src/dkg/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod lib;
23 changes: 18 additions & 5 deletions frost-uniffi-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;

#[cfg(feature = "redpallas")]
pub mod randomized;

pub mod coordinator;
pub mod dkg;
pub mod participant;
#[cfg(feature = "redpallas")]
pub mod randomized;
pub mod trusted_dealer;
use crate::frost::Error;
use crate::trusted_dealer::{trusted_dealer_keygen, trusted_dealer_keygen_from_configuration};
Expand Down Expand Up @@ -83,8 +83,22 @@ pub enum FrostError {
InvalidKeyPackage,
#[error("Secret Key couldn't be verified")]
InvalidSecretKey,
#[error("DKG couldn't be started because of an invalid number of signers")]
InvalidConfiguration,
#[error("DKG part 2 couldn't be started because of an invalid number of commitments")]
DKGPart2IncorrectNumberOfCommitments,
#[error("DKG part 2 couldn't be started because of an invalid number of packages")]
DKGPart2IncorrectNumberOfPackages,
#[error("DKG part 3 couldn't be started because packages for round 1 are incorrect or corrupted.")]
DKGPart3IncorrectRound1Packages,
#[error("DKG part 3 couldn't be started because of an invalid number of packages.")]
DKGPart3IncorrectNumberOfPackages,
#[error("A sender identified from round 1 is not present within round 2 packages.")]
DKGPart3PackageSendersMismatch,
#[error("Unknown Identifier")]
UnknownIdentifier,
#[error("Unexpected Error")]
UnexpectedError,
}
#[uniffi::export]
pub fn validate_config(config: &Configuration) -> Result<(), ConfigurationError> {
Expand Down Expand Up @@ -208,8 +222,7 @@ impl ParticipantIdentifier {
}

pub fn into_identifier(&self) -> Result<Identifier, Error> {
let raw_bytes = hex::decode(self.data.clone())
.map_err(|_| Error::DeserializationError)?;
let raw_bytes = hex::decode(self.data.clone()).map_err(|_| Error::DeserializationError)?;

let raw_identifier = raw_bytes[0..32]
.try_into()
Expand Down
2 changes: 1 addition & 1 deletion frost-uniffi-sdk/src/randomized/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pub mod coordinator;
pub mod participant;
#[cfg(feature = "redpallas")]
pub mod randomizer;
pub mod tests;
pub mod tests;
Loading

0 comments on commit 98736ce

Please sign in to comment.