From 85d6248642f1f649022804721362f78cabfc0f28 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Tue, 11 Jun 2024 14:24:06 -0300 Subject: [PATCH] [#39] Support DKG This commit adds support for part 2 and 3 of DKG see https://frost.zfnd.org/tutorial/dkg.html dkg_integration_tests.rs tests the funcitonality and explains how DKG should be performed Closes #39 --- .../FrostSwiftFFI/frost_uniffi_sdk.swift | 554 +++++++++++++- Scripts/build_go.sh | 14 +- Scripts/build_go_bindings.sh | 18 +- Scripts/replace_remote_binary_with_local.sh | 11 +- Scripts/test_bindings.sh | 15 - frost-uniffi-sdk/src/dkg/lib.rs | 232 ++++++ frost-uniffi-sdk/src/dkg/mod.rs | 1 + frost-uniffi-sdk/src/lib.rs | 23 +- frost-uniffi-sdk/src/randomized/mod.rs | 2 +- .../src/randomized/tests/helpers.rs | 18 +- frost-uniffi-sdk/src/randomized/tests/mod.rs | 2 +- .../tests/dkg_integration_tests.rs | 217 ++++++ frost-uniffi-sdk/tests/helpers.rs | 3 +- frost-uniffi-sdk/tests/integration_tests.rs | 13 +- frost_go_ffi/frost_go_ffi.h | 52 ++ frost_go_ffi/frost_uniffi_sdk.go | 676 +++++++++++++++++- 16 files changed, 1774 insertions(+), 77 deletions(-) create mode 100644 frost-uniffi-sdk/src/dkg/lib.rs create mode 100644 frost-uniffi-sdk/src/dkg/mod.rs create mode 100644 frost-uniffi-sdk/tests/dkg_integration_tests.rs diff --git a/FrostSwift/Sources/FrostSwiftFFI/frost_uniffi_sdk.swift b/FrostSwift/Sources/FrostSwiftFFI/frost_uniffi_sdk.swift index 70d1800..a133a9e 100644 --- a/FrostSwift/Sources/FrostSwiftFFI/frost_uniffi_sdk.swift +++ b/FrostSwift/Sources/FrostSwiftFFI/frost_uniffi_sdk.swift @@ -364,6 +364,262 @@ fileprivate struct FfiConverterData: FfiConverterRustBuffer { } +public protocol DKGPart1ResultProtocol { + +} + +public class DkgPart1Result: DKGPart1ResultProtocol { + fileprivate let pointer: UnsafeMutableRawPointer + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + deinit { + try! rustCall { uniffi_frost_uniffi_sdk_fn_free_dkgpart1result(pointer, $0) } + } + + + + + +} + +public struct FfiConverterTypeDKGPart1Result: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = DkgPart1Result + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgPart1Result { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if (ptr == nil) { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: DkgPart1Result, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgPart1Result { + return DkgPart1Result(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: DkgPart1Result) -> UnsafeMutableRawPointer { + return value.pointer + } +} + + +public func FfiConverterTypeDKGPart1Result_lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgPart1Result { + return try FfiConverterTypeDKGPart1Result.lift(pointer) +} + +public func FfiConverterTypeDKGPart1Result_lower(_ value: DkgPart1Result) -> UnsafeMutableRawPointer { + return FfiConverterTypeDKGPart1Result.lower(value) +} + + +public protocol DKGPart2ResultProtocol { + +} + +public class DkgPart2Result: DKGPart2ResultProtocol { + fileprivate let pointer: UnsafeMutableRawPointer + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + deinit { + try! rustCall { uniffi_frost_uniffi_sdk_fn_free_dkgpart2result(pointer, $0) } + } + + + + + +} + +public struct FfiConverterTypeDKGPart2Result: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = DkgPart2Result + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgPart2Result { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if (ptr == nil) { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: DkgPart2Result, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgPart2Result { + return DkgPart2Result(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: DkgPart2Result) -> UnsafeMutableRawPointer { + return value.pointer + } +} + + +public func FfiConverterTypeDKGPart2Result_lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgPart2Result { + return try FfiConverterTypeDKGPart2Result.lift(pointer) +} + +public func FfiConverterTypeDKGPart2Result_lower(_ value: DkgPart2Result) -> UnsafeMutableRawPointer { + return FfiConverterTypeDKGPart2Result.lower(value) +} + + +public protocol DKGRound1SecretPackageProtocol { + +} + +public class DkgRound1SecretPackage: DKGRound1SecretPackageProtocol { + fileprivate let pointer: UnsafeMutableRawPointer + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + deinit { + try! rustCall { uniffi_frost_uniffi_sdk_fn_free_dkground1secretpackage(pointer, $0) } + } + + + + + +} + +public struct FfiConverterTypeDKGRound1SecretPackage: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = DkgRound1SecretPackage + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgRound1SecretPackage { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if (ptr == nil) { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: DkgRound1SecretPackage, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgRound1SecretPackage { + return DkgRound1SecretPackage(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: DkgRound1SecretPackage) -> UnsafeMutableRawPointer { + return value.pointer + } +} + + +public func FfiConverterTypeDKGRound1SecretPackage_lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgRound1SecretPackage { + return try FfiConverterTypeDKGRound1SecretPackage.lift(pointer) +} + +public func FfiConverterTypeDKGRound1SecretPackage_lower(_ value: DkgRound1SecretPackage) -> UnsafeMutableRawPointer { + return FfiConverterTypeDKGRound1SecretPackage.lower(value) +} + + +public protocol DKGRound2SecretPackageProtocol { + +} + +public class DkgRound2SecretPackage: DKGRound2SecretPackageProtocol { + fileprivate let pointer: UnsafeMutableRawPointer + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + deinit { + try! rustCall { uniffi_frost_uniffi_sdk_fn_free_dkground2secretpackage(pointer, $0) } + } + + + + + +} + +public struct FfiConverterTypeDKGRound2SecretPackage: FfiConverter { + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = DkgRound2SecretPackage + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgRound2SecretPackage { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if (ptr == nil) { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: DkgRound2SecretPackage, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgRound2SecretPackage { + return DkgRound2SecretPackage(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: DkgRound2SecretPackage) -> UnsafeMutableRawPointer { + return value.pointer + } +} + + +public func FfiConverterTypeDKGRound2SecretPackage_lift(_ pointer: UnsafeMutableRawPointer) throws -> DkgRound2SecretPackage { + return try FfiConverterTypeDKGRound2SecretPackage.lift(pointer) +} + +public func FfiConverterTypeDKGRound2SecretPackage_lower(_ value: DkgRound2SecretPackage) -> UnsafeMutableRawPointer { + return FfiConverterTypeDKGRound2SecretPackage.lower(value) +} + + public struct Configuration { public var minSigners: UInt16 public var maxSigners: UInt16 @@ -427,6 +683,171 @@ public func FfiConverterTypeConfiguration_lower(_ value: Configuration) -> RustB } +public struct DkgPart3Result { + public var publicKeyPackage: FrostPublicKeyPackage + public var keyPackage: FrostKeyPackage + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(publicKeyPackage: FrostPublicKeyPackage, keyPackage: FrostKeyPackage) { + self.publicKeyPackage = publicKeyPackage + self.keyPackage = keyPackage + } +} + + +extension DkgPart3Result: Equatable, Hashable { + public static func ==(lhs: DkgPart3Result, rhs: DkgPart3Result) -> Bool { + if lhs.publicKeyPackage != rhs.publicKeyPackage { + return false + } + if lhs.keyPackage != rhs.keyPackage { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(publicKeyPackage) + hasher.combine(keyPackage) + } +} + + +public struct FfiConverterTypeDKGPart3Result: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgPart3Result { + return try DkgPart3Result( + publicKeyPackage: FfiConverterTypeFrostPublicKeyPackage.read(from: &buf), + keyPackage: FfiConverterTypeFrostKeyPackage.read(from: &buf) + ) + } + + public static func write(_ value: DkgPart3Result, into buf: inout [UInt8]) { + FfiConverterTypeFrostPublicKeyPackage.write(value.publicKeyPackage, into: &buf) + FfiConverterTypeFrostKeyPackage.write(value.keyPackage, into: &buf) + } +} + + +public func FfiConverterTypeDKGPart3Result_lift(_ buf: RustBuffer) throws -> DkgPart3Result { + return try FfiConverterTypeDKGPart3Result.lift(buf) +} + +public func FfiConverterTypeDKGPart3Result_lower(_ value: DkgPart3Result) -> RustBuffer { + return FfiConverterTypeDKGPart3Result.lower(value) +} + + +public struct DkgRound1Package { + public var identifier: ParticipantIdentifier + public var data: Data + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(identifier: ParticipantIdentifier, data: Data) { + self.identifier = identifier + self.data = data + } +} + + +extension DkgRound1Package: Equatable, Hashable { + public static func ==(lhs: DkgRound1Package, rhs: DkgRound1Package) -> Bool { + if lhs.identifier != rhs.identifier { + return false + } + if lhs.data != rhs.data { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(identifier) + hasher.combine(data) + } +} + + +public struct FfiConverterTypeDKGRound1Package: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgRound1Package { + return try DkgRound1Package( + identifier: FfiConverterTypeParticipantIdentifier.read(from: &buf), + data: FfiConverterData.read(from: &buf) + ) + } + + public static func write(_ value: DkgRound1Package, into buf: inout [UInt8]) { + FfiConverterTypeParticipantIdentifier.write(value.identifier, into: &buf) + FfiConverterData.write(value.data, into: &buf) + } +} + + +public func FfiConverterTypeDKGRound1Package_lift(_ buf: RustBuffer) throws -> DkgRound1Package { + return try FfiConverterTypeDKGRound1Package.lift(buf) +} + +public func FfiConverterTypeDKGRound1Package_lower(_ value: DkgRound1Package) -> RustBuffer { + return FfiConverterTypeDKGRound1Package.lower(value) +} + + +public struct DkgRound2Package { + public var identifier: ParticipantIdentifier + public var data: Data + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(identifier: ParticipantIdentifier, data: Data) { + self.identifier = identifier + self.data = data + } +} + + +extension DkgRound2Package: Equatable, Hashable { + public static func ==(lhs: DkgRound2Package, rhs: DkgRound2Package) -> Bool { + if lhs.identifier != rhs.identifier { + return false + } + if lhs.data != rhs.data { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(identifier) + hasher.combine(data) + } +} + + +public struct FfiConverterTypeDKGRound2Package: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DkgRound2Package { + return try DkgRound2Package( + identifier: FfiConverterTypeParticipantIdentifier.read(from: &buf), + data: FfiConverterData.read(from: &buf) + ) + } + + public static func write(_ value: DkgRound2Package, into buf: inout [UInt8]) { + FfiConverterTypeParticipantIdentifier.write(value.identifier, into: &buf) + FfiConverterData.write(value.data, into: &buf) + } +} + + +public func FfiConverterTypeDKGRound2Package_lift(_ buf: RustBuffer) throws -> DkgRound2Package { + return try FfiConverterTypeDKGRound2Package.lift(buf) +} + +public func FfiConverterTypeDKGRound2Package_lower(_ value: DkgRound2Package) -> RustBuffer { + return FfiConverterTypeDKGRound2Package.lower(value) +} + + public struct FirstRoundCommitment { public var nonces: FrostSigningNonces public var commitments: FrostSigningCommitments @@ -1252,7 +1673,14 @@ public enum FrostError { case DeserializationError case InvalidKeyPackage case InvalidSecretKey + case InvalidConfiguration + case DkgPart2IncorrectNumberOfCommitments + case DkgPart2IncorrectNumberOfPackages + case DkgPart3IncorrectRound1Packages + case DkgPart3IncorrectNumberOfPackages + case DkgPart3PackageSendersMismatch case UnknownIdentifier + case UnexpectedError fileprivate static func uniffiErrorHandler(_ error: RustBuffer) throws -> Error { return try FfiConverterTypeFrostError.lift(error) @@ -1274,7 +1702,14 @@ public struct FfiConverterTypeFrostError: FfiConverterRustBuffer { case 2: return .DeserializationError case 3: return .InvalidKeyPackage case 4: return .InvalidSecretKey - case 5: return .UnknownIdentifier + case 5: return .InvalidConfiguration + case 6: return .DkgPart2IncorrectNumberOfCommitments + case 7: return .DkgPart2IncorrectNumberOfPackages + case 8: return .DkgPart3IncorrectRound1Packages + case 9: return .DkgPart3IncorrectNumberOfPackages + case 10: return .DkgPart3PackageSendersMismatch + case 11: return .UnknownIdentifier + case 12: return .UnexpectedError default: throw UniffiInternalError.unexpectedEnumCase } @@ -1303,9 +1738,37 @@ public struct FfiConverterTypeFrostError: FfiConverterRustBuffer { writeInt(&buf, Int32(4)) - case .UnknownIdentifier: + case .InvalidConfiguration: writeInt(&buf, Int32(5)) + + case .DkgPart2IncorrectNumberOfCommitments: + writeInt(&buf, Int32(6)) + + + case .DkgPart2IncorrectNumberOfPackages: + writeInt(&buf, Int32(7)) + + + case .DkgPart3IncorrectRound1Packages: + writeInt(&buf, Int32(8)) + + + case .DkgPart3IncorrectNumberOfPackages: + writeInt(&buf, Int32(9)) + + + case .DkgPart3PackageSendersMismatch: + writeInt(&buf, Int32(10)) + + + case .UnknownIdentifier: + writeInt(&buf, Int32(11)) + + + case .UnexpectedError: + writeInt(&buf, Int32(12)) + } } } @@ -1593,6 +2056,52 @@ fileprivate struct FfiConverterDictionaryTypeParticipantIdentifierString: FfiCon } } +fileprivate struct FfiConverterDictionaryTypeParticipantIdentifierTypeDKGRound1Package: FfiConverterRustBuffer { + public static func write(_ value: [ParticipantIdentifier: DkgRound1Package], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for (key, value) in value { + FfiConverterTypeParticipantIdentifier.write(key, into: &buf) + FfiConverterTypeDKGRound1Package.write(value, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [ParticipantIdentifier: DkgRound1Package] { + let len: Int32 = try readInt(&buf) + var dict = [ParticipantIdentifier: DkgRound1Package]() + dict.reserveCapacity(Int(len)) + for _ in 0.. [ParticipantIdentifier: DkgRound2Package] { + let len: Int32 = try readInt(&buf) + var dict = [ParticipantIdentifier: DkgRound2Package]() + dict.reserveCapacity(Int(len)) + for _ in 0.. DkgPart1Result { + return try FfiConverterTypeDKGPart1Result.lift( + try rustCallWithError(FfiConverterTypeFrostError.lift) { + uniffi_frost_uniffi_sdk_fn_func_part_1( + FfiConverterTypeParticipantIdentifier.lower(participantIdentifier), + FfiConverterUInt16.lower(maxSigners), + FfiConverterUInt16.lower(minSigners),$0) +} + ) +} + +public func part2(secretPackage: DkgRound1SecretPackage, round1Packages: [ParticipantIdentifier: DkgRound1Package]) throws -> DkgPart2Result { + return try FfiConverterTypeDKGPart2Result.lift( + try rustCallWithError(FfiConverterTypeFrostError.lift) { + uniffi_frost_uniffi_sdk_fn_func_part_2( + FfiConverterTypeDKGRound1SecretPackage.lower(secretPackage), + FfiConverterDictionaryTypeParticipantIdentifierTypeDKGRound1Package.lower(round1Packages),$0) +} + ) +} + +public func part3(secretPackage: DkgRound2SecretPackage, round1Packages: [ParticipantIdentifier: DkgRound1Package], round2Packages: [ParticipantIdentifier: DkgRound2Package]) throws -> DkgPart3Result { + return try FfiConverterTypeDKGPart3Result.lift( + try rustCallWithError(FfiConverterTypeFrostError.lift) { + uniffi_frost_uniffi_sdk_fn_func_part_3( + FfiConverterTypeDKGRound2SecretPackage.lower(secretPackage), + FfiConverterDictionaryTypeParticipantIdentifierTypeDKGRound1Package.lower(round1Packages), + FfiConverterDictionaryTypeParticipantIdentifierTypeDKGRound2Package.lower(round2Packages),$0) +} + ) +} + public func sign(signingPackage: FrostSigningPackage, nonces: FrostSigningNonces, keyPackage: FrostKeyPackage) throws -> FrostSignatureShare { return try FfiConverterTypeFrostSignatureShare.lift( try rustCallWithError(FfiConverterTypeRound2Error.lift) { @@ -1729,6 +2270,15 @@ private var initializationResult: InitializationResult { if (uniffi_frost_uniffi_sdk_checksum_func_new_signing_package() != 50111) { return InitializationResult.apiChecksumMismatch } + if (uniffi_frost_uniffi_sdk_checksum_func_part_1() != 7592) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_frost_uniffi_sdk_checksum_func_part_2() != 30136) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_frost_uniffi_sdk_checksum_func_part_3() != 31134) { + return InitializationResult.apiChecksumMismatch + } if (uniffi_frost_uniffi_sdk_checksum_func_sign() != 48101) { return InitializationResult.apiChecksumMismatch } diff --git a/Scripts/build_go.sh b/Scripts/build_go.sh index 562f1c0..ed61ad0 100644 --- a/Scripts/build_go.sh +++ b/Scripts/build_go.sh @@ -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 diff --git a/Scripts/build_go_bindings.sh b/Scripts/build_go_bindings.sh index 991afc0..311f5a9 100644 --- a/Scripts/build_go_bindings.sh +++ b/Scripts/build_go_bindings.sh @@ -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 . \ No newline at end of file diff --git a/Scripts/replace_remote_binary_with_local.sh b/Scripts/replace_remote_binary_with_local.sh index 1e5004a..7ac58c7 100644 --- a/Scripts/replace_remote_binary_with_local.sh +++ b/Scripts/replace_remote_binary_with_local.sh @@ -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 \ No newline at end of file + +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 + + diff --git a/Scripts/test_bindings.sh b/Scripts/test_bindings.sh index 5f83973..47f2ee5 100755 --- a/Scripts/test_bindings.sh +++ b/Scripts/test_bindings.sh @@ -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" diff --git a/frost-uniffi-sdk/src/dkg/lib.rs b/frost-uniffi-sdk/src/dkg/lib.rs new file mode 100644 index 0000000..fb5b2ab --- /dev/null +++ b/frost-uniffi-sdk/src/dkg/lib.rs @@ -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, +} + +#[derive(uniffi::Record, Clone)] +pub struct DKGRound2Package { + // to whom this should be send to + pub identifier: ParticipantIdentifier, + // wrapped data + pub data: Vec, +} + +impl DKGRound2Package { + fn from_package( + identifier: ParticipantIdentifier, + package: round2::Package, + ) -> Result { + Ok(DKGRound2Package { + identifier: identifier, + data: package.serialize()?, + }) + } + + fn into_package(&self) -> Result { + 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, +} + +impl DKGRound1Package { + fn into_package(&self) -> Result { + Ok(Package::deserialize(&self.data)?) + } + + fn from_package( + identifier: ParticipantIdentifier, + package: Package, + ) -> Result { + Ok(DKGRound1Package { + identifier: identifier, + data: package.serialize()?, + }) + } +} + +#[uniffi::export] +pub fn part_1( + participant_identifier: ParticipantIdentifier, + max_signers: u16, + min_signers: u16, +) -> Result, 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, + round1_packages: HashMap, +) -> Result, FrostError> { + let secret_package = secret_package.data.clone(); + + let mut packages: BTreeMap = 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 = 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, + round1_packages: HashMap, + round2_packages: HashMap, +) -> Result { + let secret_package = secret_package.data.clone(); + + let mut round1_pkg: BTreeMap = 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 = 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)?, + }) +} diff --git a/frost-uniffi-sdk/src/dkg/mod.rs b/frost-uniffi-sdk/src/dkg/mod.rs new file mode 100644 index 0000000..965f28e --- /dev/null +++ b/frost-uniffi-sdk/src/dkg/mod.rs @@ -0,0 +1 @@ +pub mod lib; diff --git a/frost-uniffi-sdk/src/lib.rs b/frost-uniffi-sdk/src/lib.rs index 0b5fc58..251cfdb 100644 --- a/frost-uniffi-sdk/src/lib.rs +++ b/frost-uniffi-sdk/src/lib.rs @@ -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}; @@ -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> { @@ -208,8 +222,7 @@ impl ParticipantIdentifier { } pub fn into_identifier(&self) -> Result { - 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() diff --git a/frost-uniffi-sdk/src/randomized/mod.rs b/frost-uniffi-sdk/src/randomized/mod.rs index 283477e..ef67d80 100644 --- a/frost-uniffi-sdk/src/randomized/mod.rs +++ b/frost-uniffi-sdk/src/randomized/mod.rs @@ -2,4 +2,4 @@ pub mod coordinator; pub mod participant; #[cfg(feature = "redpallas")] pub mod randomizer; -pub mod tests; \ No newline at end of file +pub mod tests; diff --git a/frost-uniffi-sdk/src/randomized/tests/helpers.rs b/frost-uniffi-sdk/src/randomized/tests/helpers.rs index 0356854..dd4d3db 100644 --- a/frost-uniffi-sdk/src/randomized/tests/helpers.rs +++ b/frost-uniffi-sdk/src/randomized/tests/helpers.rs @@ -7,10 +7,9 @@ use crate::coordinator::new_signing_package; use crate::randomized::participant::sign; use crate::randomized::randomizer::FrostRandomizer; use crate::{ - ParticipantIdentifier, - participant::{FrostSigningNonces, FrostSigningCommitments, FrostSignatureShare}, - FrostKeyPackage, - coordinator::{Message, FrostSigningPackage}, + coordinator::{FrostSigningPackage, Message}, + participant::{FrostSignatureShare, FrostSigningCommitments, FrostSigningNonces}, + FrostKeyPackage, ParticipantIdentifier, }; pub fn round_2( @@ -45,16 +44,11 @@ pub fn round_2( let nonces = nonces_map[participant_identifier].clone(); - let signature_share = sign( - signing_package.clone(), - nonces, - key_package, - &randomizer, - ) - .unwrap(); + let signature_share = + sign(signing_package.clone(), nonces, key_package, &randomizer).unwrap(); signature_shares.insert(participant_identifier.clone(), signature_share); } (signing_package, signature_shares, Some(randomizer)) -} \ No newline at end of file +} diff --git a/frost-uniffi-sdk/src/randomized/tests/mod.rs b/frost-uniffi-sdk/src/randomized/tests/mod.rs index eadef2b..1630fab 100644 --- a/frost-uniffi-sdk/src/randomized/tests/mod.rs +++ b/frost-uniffi-sdk/src/randomized/tests/mod.rs @@ -1 +1 @@ -pub mod helpers; \ No newline at end of file +pub mod helpers; diff --git a/frost-uniffi-sdk/tests/dkg_integration_tests.rs b/frost-uniffi-sdk/tests/dkg_integration_tests.rs new file mode 100644 index 0000000..be53ac5 --- /dev/null +++ b/frost-uniffi-sdk/tests/dkg_integration_tests.rs @@ -0,0 +1,217 @@ +use frost_ed25519::Identifier; +use frost_uniffi_sdk::coordinator::{aggregate, verify_signature}; +use rand::thread_rng; +use std::{collections::HashMap, sync::Arc}; + +use frost_uniffi_sdk::{coordinator::Message, FrostKeyPackage, FrostPublicKeyPackage, ParticipantIdentifier}; + +use frost_uniffi_sdk::dkg::lib::{ + part_1, part_2, part_3, DKGRound1Package, DKGRound1SecretPackage, DKGRound2Package, + DKGRound2SecretPackage, +}; +mod helpers; +use helpers::{key_package, round_1, round_2}; + +struct Participant { + pub identifier: ParticipantIdentifier, + min_signers: u16, + max_signers: u16, + secret1: Option, + secret2: Option, + round1_packages: Option>, + key_package: Option, + round2_packages: HashMap, + public_key_package: Option, +} + +impl Participant { + fn do_part1(&mut self) -> DKGRound1Package { + let part1 = part_1(self.identifier.clone(), self.max_signers, self.min_signers).unwrap(); + + self.secret1 = Some(part1.secret.clone()); + + part1.package.clone() + } + + fn do_part2( + &mut self, + round1_packages: HashMap, + ) -> Vec { + let mut round1_packages_except_myself = round1_packages.clone(); + round1_packages_except_myself.remove(&self.identifier); + + self.round1_packages = Some(round1_packages_except_myself); + + let r1_pkg = self.round1_packages.clone().unwrap(); + let part2 = part_2(Arc::new(self.secret1.clone().unwrap()), r1_pkg).unwrap(); + + // keep secret for later + self.secret2 = Some(part2.clone().secret.clone()); + + part2.clone().packages.clone() + } + + fn do_part3(&mut self) -> (FrostKeyPackage, FrostPublicKeyPackage) { + let part3 = part_3( + Arc::new(self.secret2.clone().unwrap()), + self.round1_packages.clone().unwrap(), + self.round2_packages.clone(), + ) + .unwrap(); + + self.key_package = Some(part3.key_package.clone()); + self.public_key_package = Some(part3.public_key_package.clone()); + + (part3.key_package, part3.public_key_package) + } + + fn receive_round2_package(&mut self, sender: ParticipantIdentifier, package: DKGRound2Package) { + self.round2_packages.insert(sender.clone(), package.clone()); + } +} + +#[test] +fn test_dkg_from_configuration_with_secret() { + let mut participants: HashMap = HashMap::new(); + let p1_identifier = ParticipantIdentifier { + data: "0100000000000000000000000000000000000000000000000000000000000000".to_string(), + }; + + participants.insert( + p1_identifier.clone(), + Participant { + identifier: p1_identifier.clone(), + min_signers: 2, + max_signers: 3, + secret1: None, + secret2: None, + round1_packages: None, + key_package: None, + round2_packages: HashMap::new(), + public_key_package: None, + }, + ); + + let p2_identifier = ParticipantIdentifier { + data: "0200000000000000000000000000000000000000000000000000000000000000".to_string(), + }; + participants.insert( + p2_identifier.clone(), + Participant { + identifier: p2_identifier, + min_signers: 2, + max_signers: 3, + secret1: None, + secret2: None, + round1_packages: None, + key_package: None, + round2_packages: HashMap::new(), + public_key_package: None, + }, + ); + + let p3_identifier = ParticipantIdentifier { + data: "0300000000000000000000000000000000000000000000000000000000000000".to_string(), + }; + + participants.insert( + p3_identifier.clone(), + Participant { + identifier: p3_identifier, + min_signers: 2, + max_signers: 3, + secret1: None, + secret2: None, + round1_packages: None, + key_package: None, + round2_packages: HashMap::new(), + public_key_package: None, + }, + ); + + // gather part1 from all participants + let mut round1_packages: HashMap = HashMap::new(); + + for (identifier, participant) in participants.iter_mut() { + round1_packages.insert(identifier.clone(), participant.do_part1()); + } + + // do part2. this HashMap key will contain who generated the packages and the values will + // be the recipients of them. + let mut round2_packages: HashMap> = HashMap::new(); + + for (identifier, participant) in participants.iter_mut() { + let packages = participant.do_part2(round1_packages.clone()); + round2_packages.insert(identifier.clone(), packages); + } + + // now each participant has to receive the round::package from their peers + // We need to give every the their round 2 packages generated on by the other n-1 participants + for (originating_participant, generated_packages) in round2_packages { + for pkg in generated_packages { + let recipient = participants.get_mut(&pkg.identifier).unwrap(); + + recipient.receive_round2_package(originating_participant.clone(), pkg); + } + } + + let mut keys: HashMap = + HashMap::new(); + + // do part 3. + for (identifier, participant) in participants.iter_mut() { + keys.insert(identifier.clone(), participant.do_part3()); + } + + assert_eq!(keys.len(), 3); + + // sign + + let mut key_packages: HashMap = HashMap::new(); + let mut pubkeys: HashMap = HashMap::new(); + + for k in keys.into_iter() { + key_packages.insert(k.0.clone(), k.1.0.clone()); + pubkeys.insert(k.0, k.1.1.clone()); + } + + let mut rng = thread_rng(); + let (nonces, commitments) = round_1(&mut rng, &key_packages); + let message = Message { + data: "i am a message".as_bytes().to_vec(), + }; + + #[cfg(feature = "redpallas")] + let (signing_package, signature_shares, randomizer) = round_2( + &mut rng, + &nonces, + &key_packages, + commitments, + message.clone(), + None, + ); + + #[cfg(not(feature = "redpallas"))] + let (signing_package, signature_shares) = + round_2(&nonces, &key_packages, commitments, message.clone()); + + let p1identifier = p1_identifier.clone(); + let pubkey = pubkeys.get(&p1identifier).unwrap().clone(); + let group_signature = aggregate( + signing_package, + signature_shares.into_iter().map(|s| s.1).collect(), + pubkey.clone(), + #[cfg(feature = "redpallas")] + randomizer.unwrap(), + ) + .unwrap(); + + let verify_signature = verify_signature(message, group_signature, pubkey.clone()); + + match verify_signature { + Ok(()) => assert!(true), + Err(e) => { + assert!(false, "signature verification failed with error: {e:?}") + } + } +} diff --git a/frost-uniffi-sdk/tests/helpers.rs b/frost-uniffi-sdk/tests/helpers.rs index a2c60d1..15f7924 100644 --- a/frost-uniffi-sdk/tests/helpers.rs +++ b/frost-uniffi-sdk/tests/helpers.rs @@ -5,12 +5,11 @@ use reddsa::frost::redpallas as frost; #[cfg(not(feature = "redpallas"))] use frost_uniffi_sdk::{ - participant::sign, coordinator::{new_signing_package, FrostSigningPackage, Message}, + participant::sign, participant::FrostSignatureShare, }; - use frost_uniffi_sdk::{ participant::{FrostSigningCommitments, FrostSigningNonces}, FrostKeyPackage, FrostSecretKeyShare, ParticipantIdentifier, diff --git a/frost-uniffi-sdk/tests/integration_tests.rs b/frost-uniffi-sdk/tests/integration_tests.rs index 3c032fb..4a91ff3 100644 --- a/frost-uniffi-sdk/tests/integration_tests.rs +++ b/frost-uniffi-sdk/tests/integration_tests.rs @@ -8,21 +8,18 @@ use frost_uniffi_sdk::{ use helpers::{key_package, round_1}; use rand::thread_rng; -#[cfg(feature = "redpallas")] -use frost_uniffi_sdk::{ - randomized::tests::helpers::round_2, - randomized::coordinator::aggregate -}; #[cfg(not(feature = "redpallas"))] use frost_uniffi_sdk::coordinator::aggregate; +#[cfg(feature = "redpallas")] +use frost_uniffi_sdk::{randomized::coordinator::aggregate, randomized::tests::helpers::round_2}; #[cfg(not(feature = "redpallas"))] use helpers::round_2; - fn test_signing_key() -> Vec { #[cfg(feature = "redpallas")] - return hex::decode("f500df73b2b416bec6a2b6bbb44e97164e05520b63aa27554cfc7ba82f5ba215").unwrap(); - + return hex::decode("f500df73b2b416bec6a2b6bbb44e97164e05520b63aa27554cfc7ba82f5ba215") + .unwrap(); + #[cfg(not(feature = "redpallas"))] return vec![ 123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2, diff --git a/frost_go_ffi/frost_go_ffi.h b/frost_go_ffi/frost_go_ffi.h index 42e82e2..b1d7bfb 100644 --- a/frost_go_ffi/frost_go_ffi.h +++ b/frost_go_ffi/frost_go_ffi.h @@ -68,6 +68,26 @@ int8_t uniffiForeignExecutorCallbackfrost_go_ffi(uint64_t, uint32_t, RustTaskCal void uniffiFutureContinuationCallbackfrost_go_ffi(void*, int8_t); +void uniffi_frost_uniffi_sdk_fn_free_dkgpart1result( + void* ptr, + RustCallStatus* out_status +); + +void uniffi_frost_uniffi_sdk_fn_free_dkgpart2result( + void* ptr, + RustCallStatus* out_status +); + +void uniffi_frost_uniffi_sdk_fn_free_dkground1secretpackage( + void* ptr, + RustCallStatus* out_status +); + +void uniffi_frost_uniffi_sdk_fn_free_dkground2secretpackage( + void* ptr, + RustCallStatus* out_status +); + RustBuffer uniffi_frost_uniffi_sdk_fn_func_aggregate( RustBuffer signing_package, RustBuffer signature_shares, @@ -86,6 +106,26 @@ RustBuffer uniffi_frost_uniffi_sdk_fn_func_new_signing_package( RustCallStatus* out_status ); +void* uniffi_frost_uniffi_sdk_fn_func_part_1( + RustBuffer participant_identifier, + uint16_t max_signers, + uint16_t min_signers, + RustCallStatus* out_status +); + +void* uniffi_frost_uniffi_sdk_fn_func_part_2( + void* secret_package, + RustBuffer round1_packages, + RustCallStatus* out_status +); + +RustBuffer uniffi_frost_uniffi_sdk_fn_func_part_3( + void* secret_package, + RustBuffer round1_packages, + RustBuffer round2_packages, + RustCallStatus* out_status +); + RustBuffer uniffi_frost_uniffi_sdk_fn_func_sign( RustBuffer signing_package, RustBuffer nonces, @@ -432,6 +472,18 @@ uint16_t uniffi_frost_uniffi_sdk_checksum_func_new_signing_package( RustCallStatus* out_status ); +uint16_t uniffi_frost_uniffi_sdk_checksum_func_part_1( + RustCallStatus* out_status +); + +uint16_t uniffi_frost_uniffi_sdk_checksum_func_part_2( + RustCallStatus* out_status +); + +uint16_t uniffi_frost_uniffi_sdk_checksum_func_part_3( + RustCallStatus* out_status +); + uint16_t uniffi_frost_uniffi_sdk_checksum_func_sign( RustCallStatus* out_status ); diff --git a/frost_go_ffi/frost_uniffi_sdk.go b/frost_go_ffi/frost_uniffi_sdk.go index b0d505d..ebcdee2 100644 --- a/frost_go_ffi/frost_uniffi_sdk.go +++ b/frost_go_ffi/frost_uniffi_sdk.go @@ -9,6 +9,8 @@ import ( "fmt" "io" "math" + "runtime" + "sync/atomic" "unsafe" ) @@ -369,6 +371,33 @@ func uniffiCheckChecksums() { panic("frost_uniffi_sdk: uniffi_frost_uniffi_sdk_checksum_func_new_signing_package: UniFFI API checksum mismatch") } } + { + checksum := rustCall(func(uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_frost_uniffi_sdk_checksum_func_part_1(uniffiStatus) + }) + if checksum != 7592 { + // If this happens try cleaning and rebuilding your project + panic("frost_uniffi_sdk: uniffi_frost_uniffi_sdk_checksum_func_part_1: UniFFI API checksum mismatch") + } + } + { + checksum := rustCall(func(uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_frost_uniffi_sdk_checksum_func_part_2(uniffiStatus) + }) + if checksum != 30136 { + // If this happens try cleaning and rebuilding your project + panic("frost_uniffi_sdk: uniffi_frost_uniffi_sdk_checksum_func_part_2: UniFFI API checksum mismatch") + } + } + { + checksum := rustCall(func(uniffiStatus *C.RustCallStatus) C.uint16_t { + return C.uniffi_frost_uniffi_sdk_checksum_func_part_3(uniffiStatus) + }) + if checksum != 31134 { + // If this happens try cleaning and rebuilding your project + panic("frost_uniffi_sdk: uniffi_frost_uniffi_sdk_checksum_func_part_3: UniFFI API checksum mismatch") + } + } { checksum := rustCall(func(uniffiStatus *C.RustCallStatus) C.uint16_t { return C.uniffi_frost_uniffi_sdk_checksum_func_sign(uniffiStatus) @@ -543,6 +572,253 @@ type FfiDestroyerBytes struct{} func (FfiDestroyerBytes) Destroy(_ []byte) {} +// Below is an implementation of synchronization requirements outlined in the link. +// https://github.com/mozilla/uniffi-rs/blob/0dc031132d9493ca812c3af6e7dd60ad2ea95bf0/uniffi_bindgen/src/bindings/kotlin/templates/ObjectRuntime.kt#L31 + +type FfiObject struct { + pointer unsafe.Pointer + callCounter atomic.Int64 + freeFunction func(unsafe.Pointer, *C.RustCallStatus) + destroyed atomic.Bool +} + +func newFfiObject(pointer unsafe.Pointer, freeFunction func(unsafe.Pointer, *C.RustCallStatus)) FfiObject { + return FfiObject{ + pointer: pointer, + freeFunction: freeFunction, + } +} + +func (ffiObject *FfiObject) incrementPointer(debugName string) unsafe.Pointer { + for { + counter := ffiObject.callCounter.Load() + if counter <= -1 { + panic(fmt.Errorf("%v object has already been destroyed", debugName)) + } + if counter == math.MaxInt64 { + panic(fmt.Errorf("%v object call counter would overflow", debugName)) + } + if ffiObject.callCounter.CompareAndSwap(counter, counter+1) { + break + } + } + + return ffiObject.pointer +} + +func (ffiObject *FfiObject) decrementPointer() { + if ffiObject.callCounter.Add(-1) == -1 { + ffiObject.freeRustArcPtr() + } +} + +func (ffiObject *FfiObject) destroy() { + if ffiObject.destroyed.CompareAndSwap(false, true) { + if ffiObject.callCounter.Add(-1) == -1 { + ffiObject.freeRustArcPtr() + } + } +} + +func (ffiObject *FfiObject) freeRustArcPtr() { + rustCall(func(status *C.RustCallStatus) int32 { + ffiObject.freeFunction(ffiObject.pointer, status) + return 0 + }) +} + +type DkgPart1Result struct { + ffiObject FfiObject +} + +func (object *DkgPart1Result) Destroy() { + runtime.SetFinalizer(object, nil) + object.ffiObject.destroy() +} + +type FfiConverterDKGPart1Result struct{} + +var FfiConverterDKGPart1ResultINSTANCE = FfiConverterDKGPart1Result{} + +func (c FfiConverterDKGPart1Result) Lift(pointer unsafe.Pointer) *DkgPart1Result { + result := &DkgPart1Result{ + newFfiObject( + pointer, + func(pointer unsafe.Pointer, status *C.RustCallStatus) { + C.uniffi_frost_uniffi_sdk_fn_free_dkgpart1result(pointer, status) + }), + } + runtime.SetFinalizer(result, (*DkgPart1Result).Destroy) + return result +} + +func (c FfiConverterDKGPart1Result) Read(reader io.Reader) *DkgPart1Result { + return c.Lift(unsafe.Pointer(uintptr(readUint64(reader)))) +} + +func (c FfiConverterDKGPart1Result) Lower(value *DkgPart1Result) unsafe.Pointer { + // TODO: this is bad - all synchronization from ObjectRuntime.go is discarded here, + // because the pointer will be decremented immediately after this function returns, + // and someone will be left holding onto a non-locked pointer. + pointer := value.ffiObject.incrementPointer("*DkgPart1Result") + defer value.ffiObject.decrementPointer() + return pointer +} + +func (c FfiConverterDKGPart1Result) Write(writer io.Writer, value *DkgPart1Result) { + writeUint64(writer, uint64(uintptr(c.Lower(value)))) +} + +type FfiDestroyerDkgPart1Result struct{} + +func (_ FfiDestroyerDkgPart1Result) Destroy(value *DkgPart1Result) { + value.Destroy() +} + +type DkgPart2Result struct { + ffiObject FfiObject +} + +func (object *DkgPart2Result) Destroy() { + runtime.SetFinalizer(object, nil) + object.ffiObject.destroy() +} + +type FfiConverterDKGPart2Result struct{} + +var FfiConverterDKGPart2ResultINSTANCE = FfiConverterDKGPart2Result{} + +func (c FfiConverterDKGPart2Result) Lift(pointer unsafe.Pointer) *DkgPart2Result { + result := &DkgPart2Result{ + newFfiObject( + pointer, + func(pointer unsafe.Pointer, status *C.RustCallStatus) { + C.uniffi_frost_uniffi_sdk_fn_free_dkgpart2result(pointer, status) + }), + } + runtime.SetFinalizer(result, (*DkgPart2Result).Destroy) + return result +} + +func (c FfiConverterDKGPart2Result) Read(reader io.Reader) *DkgPart2Result { + return c.Lift(unsafe.Pointer(uintptr(readUint64(reader)))) +} + +func (c FfiConverterDKGPart2Result) Lower(value *DkgPart2Result) unsafe.Pointer { + // TODO: this is bad - all synchronization from ObjectRuntime.go is discarded here, + // because the pointer will be decremented immediately after this function returns, + // and someone will be left holding onto a non-locked pointer. + pointer := value.ffiObject.incrementPointer("*DkgPart2Result") + defer value.ffiObject.decrementPointer() + return pointer +} + +func (c FfiConverterDKGPart2Result) Write(writer io.Writer, value *DkgPart2Result) { + writeUint64(writer, uint64(uintptr(c.Lower(value)))) +} + +type FfiDestroyerDkgPart2Result struct{} + +func (_ FfiDestroyerDkgPart2Result) Destroy(value *DkgPart2Result) { + value.Destroy() +} + +type DkgRound1SecretPackage struct { + ffiObject FfiObject +} + +func (object *DkgRound1SecretPackage) Destroy() { + runtime.SetFinalizer(object, nil) + object.ffiObject.destroy() +} + +type FfiConverterDKGRound1SecretPackage struct{} + +var FfiConverterDKGRound1SecretPackageINSTANCE = FfiConverterDKGRound1SecretPackage{} + +func (c FfiConverterDKGRound1SecretPackage) Lift(pointer unsafe.Pointer) *DkgRound1SecretPackage { + result := &DkgRound1SecretPackage{ + newFfiObject( + pointer, + func(pointer unsafe.Pointer, status *C.RustCallStatus) { + C.uniffi_frost_uniffi_sdk_fn_free_dkground1secretpackage(pointer, status) + }), + } + runtime.SetFinalizer(result, (*DkgRound1SecretPackage).Destroy) + return result +} + +func (c FfiConverterDKGRound1SecretPackage) Read(reader io.Reader) *DkgRound1SecretPackage { + return c.Lift(unsafe.Pointer(uintptr(readUint64(reader)))) +} + +func (c FfiConverterDKGRound1SecretPackage) Lower(value *DkgRound1SecretPackage) unsafe.Pointer { + // TODO: this is bad - all synchronization from ObjectRuntime.go is discarded here, + // because the pointer will be decremented immediately after this function returns, + // and someone will be left holding onto a non-locked pointer. + pointer := value.ffiObject.incrementPointer("*DkgRound1SecretPackage") + defer value.ffiObject.decrementPointer() + return pointer +} + +func (c FfiConverterDKGRound1SecretPackage) Write(writer io.Writer, value *DkgRound1SecretPackage) { + writeUint64(writer, uint64(uintptr(c.Lower(value)))) +} + +type FfiDestroyerDkgRound1SecretPackage struct{} + +func (_ FfiDestroyerDkgRound1SecretPackage) Destroy(value *DkgRound1SecretPackage) { + value.Destroy() +} + +type DkgRound2SecretPackage struct { + ffiObject FfiObject +} + +func (object *DkgRound2SecretPackage) Destroy() { + runtime.SetFinalizer(object, nil) + object.ffiObject.destroy() +} + +type FfiConverterDKGRound2SecretPackage struct{} + +var FfiConverterDKGRound2SecretPackageINSTANCE = FfiConverterDKGRound2SecretPackage{} + +func (c FfiConverterDKGRound2SecretPackage) Lift(pointer unsafe.Pointer) *DkgRound2SecretPackage { + result := &DkgRound2SecretPackage{ + newFfiObject( + pointer, + func(pointer unsafe.Pointer, status *C.RustCallStatus) { + C.uniffi_frost_uniffi_sdk_fn_free_dkground2secretpackage(pointer, status) + }), + } + runtime.SetFinalizer(result, (*DkgRound2SecretPackage).Destroy) + return result +} + +func (c FfiConverterDKGRound2SecretPackage) Read(reader io.Reader) *DkgRound2SecretPackage { + return c.Lift(unsafe.Pointer(uintptr(readUint64(reader)))) +} + +func (c FfiConverterDKGRound2SecretPackage) Lower(value *DkgRound2SecretPackage) unsafe.Pointer { + // TODO: this is bad - all synchronization from ObjectRuntime.go is discarded here, + // because the pointer will be decremented immediately after this function returns, + // and someone will be left holding onto a non-locked pointer. + pointer := value.ffiObject.incrementPointer("*DkgRound2SecretPackage") + defer value.ffiObject.decrementPointer() + return pointer +} + +func (c FfiConverterDKGRound2SecretPackage) Write(writer io.Writer, value *DkgRound2SecretPackage) { + writeUint64(writer, uint64(uintptr(c.Lower(value)))) +} + +type FfiDestroyerDkgRound2SecretPackage struct{} + +func (_ FfiDestroyerDkgRound2SecretPackage) Destroy(value *DkgRound2SecretPackage) { + value.Destroy() +} + type Configuration struct { MinSigners uint16 MaxSigners uint16 @@ -587,6 +863,126 @@ func (_ FfiDestroyerTypeConfiguration) Destroy(value Configuration) { value.Destroy() } +type DkgPart3Result struct { + PublicKeyPackage FrostPublicKeyPackage + KeyPackage FrostKeyPackage +} + +func (r *DkgPart3Result) Destroy() { + FfiDestroyerTypeFrostPublicKeyPackage{}.Destroy(r.PublicKeyPackage) + FfiDestroyerTypeFrostKeyPackage{}.Destroy(r.KeyPackage) +} + +type FfiConverterTypeDKGPart3Result struct{} + +var FfiConverterTypeDKGPart3ResultINSTANCE = FfiConverterTypeDKGPart3Result{} + +func (c FfiConverterTypeDKGPart3Result) Lift(rb RustBufferI) DkgPart3Result { + return LiftFromRustBuffer[DkgPart3Result](c, rb) +} + +func (c FfiConverterTypeDKGPart3Result) Read(reader io.Reader) DkgPart3Result { + return DkgPart3Result{ + FfiConverterTypeFrostPublicKeyPackageINSTANCE.Read(reader), + FfiConverterTypeFrostKeyPackageINSTANCE.Read(reader), + } +} + +func (c FfiConverterTypeDKGPart3Result) Lower(value DkgPart3Result) RustBuffer { + return LowerIntoRustBuffer[DkgPart3Result](c, value) +} + +func (c FfiConverterTypeDKGPart3Result) Write(writer io.Writer, value DkgPart3Result) { + FfiConverterTypeFrostPublicKeyPackageINSTANCE.Write(writer, value.PublicKeyPackage) + FfiConverterTypeFrostKeyPackageINSTANCE.Write(writer, value.KeyPackage) +} + +type FfiDestroyerTypeDkgPart3Result struct{} + +func (_ FfiDestroyerTypeDkgPart3Result) Destroy(value DkgPart3Result) { + value.Destroy() +} + +type DkgRound1Package struct { + Identifier ParticipantIdentifier + Data []byte +} + +func (r *DkgRound1Package) Destroy() { + FfiDestroyerTypeParticipantIdentifier{}.Destroy(r.Identifier) + FfiDestroyerBytes{}.Destroy(r.Data) +} + +type FfiConverterTypeDKGRound1Package struct{} + +var FfiConverterTypeDKGRound1PackageINSTANCE = FfiConverterTypeDKGRound1Package{} + +func (c FfiConverterTypeDKGRound1Package) Lift(rb RustBufferI) DkgRound1Package { + return LiftFromRustBuffer[DkgRound1Package](c, rb) +} + +func (c FfiConverterTypeDKGRound1Package) Read(reader io.Reader) DkgRound1Package { + return DkgRound1Package{ + FfiConverterTypeParticipantIdentifierINSTANCE.Read(reader), + FfiConverterBytesINSTANCE.Read(reader), + } +} + +func (c FfiConverterTypeDKGRound1Package) Lower(value DkgRound1Package) RustBuffer { + return LowerIntoRustBuffer[DkgRound1Package](c, value) +} + +func (c FfiConverterTypeDKGRound1Package) Write(writer io.Writer, value DkgRound1Package) { + FfiConverterTypeParticipantIdentifierINSTANCE.Write(writer, value.Identifier) + FfiConverterBytesINSTANCE.Write(writer, value.Data) +} + +type FfiDestroyerTypeDkgRound1Package struct{} + +func (_ FfiDestroyerTypeDkgRound1Package) Destroy(value DkgRound1Package) { + value.Destroy() +} + +type DkgRound2Package struct { + Identifier ParticipantIdentifier + Data []byte +} + +func (r *DkgRound2Package) Destroy() { + FfiDestroyerTypeParticipantIdentifier{}.Destroy(r.Identifier) + FfiDestroyerBytes{}.Destroy(r.Data) +} + +type FfiConverterTypeDKGRound2Package struct{} + +var FfiConverterTypeDKGRound2PackageINSTANCE = FfiConverterTypeDKGRound2Package{} + +func (c FfiConverterTypeDKGRound2Package) Lift(rb RustBufferI) DkgRound2Package { + return LiftFromRustBuffer[DkgRound2Package](c, rb) +} + +func (c FfiConverterTypeDKGRound2Package) Read(reader io.Reader) DkgRound2Package { + return DkgRound2Package{ + FfiConverterTypeParticipantIdentifierINSTANCE.Read(reader), + FfiConverterBytesINSTANCE.Read(reader), + } +} + +func (c FfiConverterTypeDKGRound2Package) Lower(value DkgRound2Package) RustBuffer { + return LowerIntoRustBuffer[DkgRound2Package](c, value) +} + +func (c FfiConverterTypeDKGRound2Package) Write(writer io.Writer, value DkgRound2Package) { + FfiConverterTypeParticipantIdentifierINSTANCE.Write(writer, value.Identifier) + FfiConverterBytesINSTANCE.Write(writer, value.Data) +} + +type FfiDestroyerTypeDkgRound2Package struct{} + +func (_ FfiDestroyerTypeDkgRound2Package) Destroy(value DkgRound2Package) { + value.Destroy() +} + type FirstRoundCommitment struct { Nonces FrostSigningNonces Commitments FrostSigningCommitments @@ -1443,7 +1839,14 @@ var ErrFrostErrorSerializationError = fmt.Errorf("FrostErrorSerializationError") var ErrFrostErrorDeserializationError = fmt.Errorf("FrostErrorDeserializationError") var ErrFrostErrorInvalidKeyPackage = fmt.Errorf("FrostErrorInvalidKeyPackage") var ErrFrostErrorInvalidSecretKey = fmt.Errorf("FrostErrorInvalidSecretKey") +var ErrFrostErrorInvalidConfiguration = fmt.Errorf("FrostErrorInvalidConfiguration") +var ErrFrostErrorDkgPart2IncorrectNumberOfCommitments = fmt.Errorf("FrostErrorDkgPart2IncorrectNumberOfCommitments") +var ErrFrostErrorDkgPart2IncorrectNumberOfPackages = fmt.Errorf("FrostErrorDkgPart2IncorrectNumberOfPackages") +var ErrFrostErrorDkgPart3IncorrectRound1Packages = fmt.Errorf("FrostErrorDkgPart3IncorrectRound1Packages") +var ErrFrostErrorDkgPart3IncorrectNumberOfPackages = fmt.Errorf("FrostErrorDkgPart3IncorrectNumberOfPackages") +var ErrFrostErrorDkgPart3PackageSendersMismatch = fmt.Errorf("FrostErrorDkgPart3PackageSendersMismatch") var ErrFrostErrorUnknownIdentifier = fmt.Errorf("FrostErrorUnknownIdentifier") +var ErrFrostErrorUnexpectedError = fmt.Errorf("FrostErrorUnexpectedError") // Variant structs type FrostErrorSerializationError struct { @@ -1514,6 +1917,108 @@ func (self FrostErrorInvalidSecretKey) Is(target error) bool { return target == ErrFrostErrorInvalidSecretKey } +type FrostErrorInvalidConfiguration struct { +} + +func NewFrostErrorInvalidConfiguration() *FrostError { + return &FrostError{ + err: &FrostErrorInvalidConfiguration{}, + } +} + +func (err FrostErrorInvalidConfiguration) Error() string { + return fmt.Sprint("InvalidConfiguration") +} + +func (self FrostErrorInvalidConfiguration) Is(target error) bool { + return target == ErrFrostErrorInvalidConfiguration +} + +type FrostErrorDkgPart2IncorrectNumberOfCommitments struct { +} + +func NewFrostErrorDkgPart2IncorrectNumberOfCommitments() *FrostError { + return &FrostError{ + err: &FrostErrorDkgPart2IncorrectNumberOfCommitments{}, + } +} + +func (err FrostErrorDkgPart2IncorrectNumberOfCommitments) Error() string { + return fmt.Sprint("DkgPart2IncorrectNumberOfCommitments") +} + +func (self FrostErrorDkgPart2IncorrectNumberOfCommitments) Is(target error) bool { + return target == ErrFrostErrorDkgPart2IncorrectNumberOfCommitments +} + +type FrostErrorDkgPart2IncorrectNumberOfPackages struct { +} + +func NewFrostErrorDkgPart2IncorrectNumberOfPackages() *FrostError { + return &FrostError{ + err: &FrostErrorDkgPart2IncorrectNumberOfPackages{}, + } +} + +func (err FrostErrorDkgPart2IncorrectNumberOfPackages) Error() string { + return fmt.Sprint("DkgPart2IncorrectNumberOfPackages") +} + +func (self FrostErrorDkgPart2IncorrectNumberOfPackages) Is(target error) bool { + return target == ErrFrostErrorDkgPart2IncorrectNumberOfPackages +} + +type FrostErrorDkgPart3IncorrectRound1Packages struct { +} + +func NewFrostErrorDkgPart3IncorrectRound1Packages() *FrostError { + return &FrostError{ + err: &FrostErrorDkgPart3IncorrectRound1Packages{}, + } +} + +func (err FrostErrorDkgPart3IncorrectRound1Packages) Error() string { + return fmt.Sprint("DkgPart3IncorrectRound1Packages") +} + +func (self FrostErrorDkgPart3IncorrectRound1Packages) Is(target error) bool { + return target == ErrFrostErrorDkgPart3IncorrectRound1Packages +} + +type FrostErrorDkgPart3IncorrectNumberOfPackages struct { +} + +func NewFrostErrorDkgPart3IncorrectNumberOfPackages() *FrostError { + return &FrostError{ + err: &FrostErrorDkgPart3IncorrectNumberOfPackages{}, + } +} + +func (err FrostErrorDkgPart3IncorrectNumberOfPackages) Error() string { + return fmt.Sprint("DkgPart3IncorrectNumberOfPackages") +} + +func (self FrostErrorDkgPart3IncorrectNumberOfPackages) Is(target error) bool { + return target == ErrFrostErrorDkgPart3IncorrectNumberOfPackages +} + +type FrostErrorDkgPart3PackageSendersMismatch struct { +} + +func NewFrostErrorDkgPart3PackageSendersMismatch() *FrostError { + return &FrostError{ + err: &FrostErrorDkgPart3PackageSendersMismatch{}, + } +} + +func (err FrostErrorDkgPart3PackageSendersMismatch) Error() string { + return fmt.Sprint("DkgPart3PackageSendersMismatch") +} + +func (self FrostErrorDkgPart3PackageSendersMismatch) Is(target error) bool { + return target == ErrFrostErrorDkgPart3PackageSendersMismatch +} + type FrostErrorUnknownIdentifier struct { } @@ -1531,6 +2036,23 @@ func (self FrostErrorUnknownIdentifier) Is(target error) bool { return target == ErrFrostErrorUnknownIdentifier } +type FrostErrorUnexpectedError struct { +} + +func NewFrostErrorUnexpectedError() *FrostError { + return &FrostError{ + err: &FrostErrorUnexpectedError{}, + } +} + +func (err FrostErrorUnexpectedError) Error() string { + return fmt.Sprint("UnexpectedError") +} + +func (self FrostErrorUnexpectedError) Is(target error) bool { + return target == ErrFrostErrorUnexpectedError +} + type FfiConverterTypeFrostError struct{} var FfiConverterTypeFrostErrorINSTANCE = FfiConverterTypeFrostError{} @@ -1556,7 +2078,21 @@ func (c FfiConverterTypeFrostError) Read(reader io.Reader) error { case 4: return &FrostError{&FrostErrorInvalidSecretKey{}} case 5: + return &FrostError{&FrostErrorInvalidConfiguration{}} + case 6: + return &FrostError{&FrostErrorDkgPart2IncorrectNumberOfCommitments{}} + case 7: + return &FrostError{&FrostErrorDkgPart2IncorrectNumberOfPackages{}} + case 8: + return &FrostError{&FrostErrorDkgPart3IncorrectRound1Packages{}} + case 9: + return &FrostError{&FrostErrorDkgPart3IncorrectNumberOfPackages{}} + case 10: + return &FrostError{&FrostErrorDkgPart3PackageSendersMismatch{}} + case 11: return &FrostError{&FrostErrorUnknownIdentifier{}} + case 12: + return &FrostError{&FrostErrorUnexpectedError{}} default: panic(fmt.Sprintf("Unknown error code %d in FfiConverterTypeFrostError.Read()", errorID)) } @@ -1572,8 +2108,22 @@ func (c FfiConverterTypeFrostError) Write(writer io.Writer, value *FrostError) { writeInt32(writer, 3) case *FrostErrorInvalidSecretKey: writeInt32(writer, 4) - case *FrostErrorUnknownIdentifier: + case *FrostErrorInvalidConfiguration: writeInt32(writer, 5) + case *FrostErrorDkgPart2IncorrectNumberOfCommitments: + writeInt32(writer, 6) + case *FrostErrorDkgPart2IncorrectNumberOfPackages: + writeInt32(writer, 7) + case *FrostErrorDkgPart3IncorrectRound1Packages: + writeInt32(writer, 8) + case *FrostErrorDkgPart3IncorrectNumberOfPackages: + writeInt32(writer, 9) + case *FrostErrorDkgPart3PackageSendersMismatch: + writeInt32(writer, 10) + case *FrostErrorUnknownIdentifier: + writeInt32(writer, 11) + case *FrostErrorUnexpectedError: + writeInt32(writer, 12) default: _ = variantValue panic(fmt.Sprintf("invalid error value `%v` in FfiConverterTypeFrostError.Write", value)) @@ -2131,6 +2681,94 @@ func (_ FfiDestroyerMapTypeParticipantIdentifierString) Destroy(mapValue map[Par } } +type FfiConverterMapTypeParticipantIdentifierTypeDKGRound1Package struct{} + +var FfiConverterMapTypeParticipantIdentifierTypeDKGRound1PackageINSTANCE = FfiConverterMapTypeParticipantIdentifierTypeDKGRound1Package{} + +func (c FfiConverterMapTypeParticipantIdentifierTypeDKGRound1Package) Lift(rb RustBufferI) map[ParticipantIdentifier]DkgRound1Package { + return LiftFromRustBuffer[map[ParticipantIdentifier]DkgRound1Package](c, rb) +} + +func (_ FfiConverterMapTypeParticipantIdentifierTypeDKGRound1Package) Read(reader io.Reader) map[ParticipantIdentifier]DkgRound1Package { + result := make(map[ParticipantIdentifier]DkgRound1Package) + length := readInt32(reader) + for i := int32(0); i < length; i++ { + key := FfiConverterTypeParticipantIdentifierINSTANCE.Read(reader) + value := FfiConverterTypeDKGRound1PackageINSTANCE.Read(reader) + result[key] = value + } + return result +} + +func (c FfiConverterMapTypeParticipantIdentifierTypeDKGRound1Package) Lower(value map[ParticipantIdentifier]DkgRound1Package) RustBuffer { + return LowerIntoRustBuffer[map[ParticipantIdentifier]DkgRound1Package](c, value) +} + +func (_ FfiConverterMapTypeParticipantIdentifierTypeDKGRound1Package) Write(writer io.Writer, mapValue map[ParticipantIdentifier]DkgRound1Package) { + if len(mapValue) > math.MaxInt32 { + panic("map[ParticipantIdentifier]DkgRound1Package is too large to fit into Int32") + } + + writeInt32(writer, int32(len(mapValue))) + for key, value := range mapValue { + FfiConverterTypeParticipantIdentifierINSTANCE.Write(writer, key) + FfiConverterTypeDKGRound1PackageINSTANCE.Write(writer, value) + } +} + +type FfiDestroyerMapTypeParticipantIdentifierTypeDkgRound1Package struct{} + +func (_ FfiDestroyerMapTypeParticipantIdentifierTypeDkgRound1Package) Destroy(mapValue map[ParticipantIdentifier]DkgRound1Package) { + for key, value := range mapValue { + FfiDestroyerTypeParticipantIdentifier{}.Destroy(key) + FfiDestroyerTypeDkgRound1Package{}.Destroy(value) + } +} + +type FfiConverterMapTypeParticipantIdentifierTypeDKGRound2Package struct{} + +var FfiConverterMapTypeParticipantIdentifierTypeDKGRound2PackageINSTANCE = FfiConverterMapTypeParticipantIdentifierTypeDKGRound2Package{} + +func (c FfiConverterMapTypeParticipantIdentifierTypeDKGRound2Package) Lift(rb RustBufferI) map[ParticipantIdentifier]DkgRound2Package { + return LiftFromRustBuffer[map[ParticipantIdentifier]DkgRound2Package](c, rb) +} + +func (_ FfiConverterMapTypeParticipantIdentifierTypeDKGRound2Package) Read(reader io.Reader) map[ParticipantIdentifier]DkgRound2Package { + result := make(map[ParticipantIdentifier]DkgRound2Package) + length := readInt32(reader) + for i := int32(0); i < length; i++ { + key := FfiConverterTypeParticipantIdentifierINSTANCE.Read(reader) + value := FfiConverterTypeDKGRound2PackageINSTANCE.Read(reader) + result[key] = value + } + return result +} + +func (c FfiConverterMapTypeParticipantIdentifierTypeDKGRound2Package) Lower(value map[ParticipantIdentifier]DkgRound2Package) RustBuffer { + return LowerIntoRustBuffer[map[ParticipantIdentifier]DkgRound2Package](c, value) +} + +func (_ FfiConverterMapTypeParticipantIdentifierTypeDKGRound2Package) Write(writer io.Writer, mapValue map[ParticipantIdentifier]DkgRound2Package) { + if len(mapValue) > math.MaxInt32 { + panic("map[ParticipantIdentifier]DkgRound2Package is too large to fit into Int32") + } + + writeInt32(writer, int32(len(mapValue))) + for key, value := range mapValue { + FfiConverterTypeParticipantIdentifierINSTANCE.Write(writer, key) + FfiConverterTypeDKGRound2PackageINSTANCE.Write(writer, value) + } +} + +type FfiDestroyerMapTypeParticipantIdentifierTypeDkgRound2Package struct{} + +func (_ FfiDestroyerMapTypeParticipantIdentifierTypeDkgRound2Package) Destroy(mapValue map[ParticipantIdentifier]DkgRound2Package) { + for key, value := range mapValue { + FfiDestroyerTypeParticipantIdentifier{}.Destroy(key) + FfiDestroyerTypeDkgRound2Package{}.Destroy(value) + } +} + type FfiConverterMapTypeParticipantIdentifierTypeFrostSecretKeyShare struct{} var FfiConverterMapTypeParticipantIdentifierTypeFrostSecretKeyShareINSTANCE = FfiConverterMapTypeParticipantIdentifierTypeFrostSecretKeyShare{} @@ -2211,6 +2849,42 @@ func NewSigningPackage(message Message, commitments []FrostSigningCommitments) ( } } +func Part1(participantIdentifier ParticipantIdentifier, maxSigners uint16, minSigners uint16) (*DkgPart1Result, error) { + _uniffiRV, _uniffiErr := rustCallWithError(FfiConverterTypeFrostError{}, func(_uniffiStatus *C.RustCallStatus) unsafe.Pointer { + return C.uniffi_frost_uniffi_sdk_fn_func_part_1(FfiConverterTypeParticipantIdentifierINSTANCE.Lower(participantIdentifier), FfiConverterUint16INSTANCE.Lower(maxSigners), FfiConverterUint16INSTANCE.Lower(minSigners), _uniffiStatus) + }) + if _uniffiErr != nil { + var _uniffiDefaultValue *DkgPart1Result + return _uniffiDefaultValue, _uniffiErr + } else { + return FfiConverterDKGPart1ResultINSTANCE.Lift(_uniffiRV), _uniffiErr + } +} + +func Part2(secretPackage *DkgRound1SecretPackage, round1Packages map[ParticipantIdentifier]DkgRound1Package) (*DkgPart2Result, error) { + _uniffiRV, _uniffiErr := rustCallWithError(FfiConverterTypeFrostError{}, func(_uniffiStatus *C.RustCallStatus) unsafe.Pointer { + return C.uniffi_frost_uniffi_sdk_fn_func_part_2(FfiConverterDKGRound1SecretPackageINSTANCE.Lower(secretPackage), FfiConverterMapTypeParticipantIdentifierTypeDKGRound1PackageINSTANCE.Lower(round1Packages), _uniffiStatus) + }) + if _uniffiErr != nil { + var _uniffiDefaultValue *DkgPart2Result + return _uniffiDefaultValue, _uniffiErr + } else { + return FfiConverterDKGPart2ResultINSTANCE.Lift(_uniffiRV), _uniffiErr + } +} + +func Part3(secretPackage *DkgRound2SecretPackage, round1Packages map[ParticipantIdentifier]DkgRound1Package, round2Packages map[ParticipantIdentifier]DkgRound2Package) (DkgPart3Result, error) { + _uniffiRV, _uniffiErr := rustCallWithError(FfiConverterTypeFrostError{}, func(_uniffiStatus *C.RustCallStatus) RustBufferI { + return C.uniffi_frost_uniffi_sdk_fn_func_part_3(FfiConverterDKGRound2SecretPackageINSTANCE.Lower(secretPackage), FfiConverterMapTypeParticipantIdentifierTypeDKGRound1PackageINSTANCE.Lower(round1Packages), FfiConverterMapTypeParticipantIdentifierTypeDKGRound2PackageINSTANCE.Lower(round2Packages), _uniffiStatus) + }) + if _uniffiErr != nil { + var _uniffiDefaultValue DkgPart3Result + return _uniffiDefaultValue, _uniffiErr + } else { + return FfiConverterTypeDKGPart3ResultINSTANCE.Lift(_uniffiRV), _uniffiErr + } +} + func Sign(signingPackage FrostSigningPackage, nonces FrostSigningNonces, keyPackage FrostKeyPackage) (FrostSignatureShare, error) { _uniffiRV, _uniffiErr := rustCallWithError(FfiConverterTypeRound2Error{}, func(_uniffiStatus *C.RustCallStatus) RustBufferI { return C.uniffi_frost_uniffi_sdk_fn_func_sign(FfiConverterTypeFrostSigningPackageINSTANCE.Lower(signingPackage), FfiConverterTypeFrostSigningNoncesINSTANCE.Lower(nonces), FfiConverterTypeFrostKeyPackageINSTANCE.Lower(keyPackage), _uniffiStatus)