From f0aa848189d4a6e05cb19837d3352dba69b4a6cb Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 1 Aug 2023 14:13:33 -0600
Subject: [PATCH 01/49] add serai submodule

---
 .gitmodules | 3 +++
 src/serai   | 1 +
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 src/serai

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..01500a7
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/serai"]
+	path = src/serai
+	url = https://github.com/kayabaNerve/serai
diff --git a/src/serai b/src/serai
new file mode 160000
index 0000000..5d4632b
--- /dev/null
+++ b/src/serai
@@ -0,0 +1 @@
+Subproject commit 5d4632bace0df2c140a1bbbb2ba487de967fa8f3

From 734658e8db7f01a8c39fd848d03ee96945d07333 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 1 Aug 2023 16:50:23 -0600
Subject: [PATCH 02/49] WIP test build scripts

---
 scripts/linux/build_all.sh      | 17 +++++++++++++++++
 scripts/linux/regen_bindings.sh |  5 +++++
 2 files changed, 22 insertions(+)
 create mode 100755 scripts/linux/build_all.sh
 create mode 100755 scripts/linux/regen_bindings.sh

diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh
new file mode 100755
index 0000000..6403307
--- /dev/null
+++ b/scripts/linux/build_all.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+ROOT_DIR="$(pwd)/../.."
+
+mkdir -p build
+
+
+cd "$ROOT_DIR"/src/serai/hrf || exit
+if [ "$IS_ARM" = true ]  ; then
+    echo "Building arm frostdart"
+    cargo build --target aarch64-unknown-linux-gnu --release --lib
+    cp ../target/aarch64-unknown-linux-gnu/release/libfrostdart.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
+else
+    echo "Building x86_64 frostdart"
+    cargo build --target x86_64-unknown-linux-gnu --release --lib
+    cp ../target/x86_64-unknown-linux-gnu/release/libfrostdart.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
+fi
\ No newline at end of file
diff --git a/scripts/linux/regen_bindings.sh b/scripts/linux/regen_bindings.sh
new file mode 100755
index 0000000..d52b878
--- /dev/null
+++ b/scripts/linux/regen_bindings.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd ../..
+
+dart run ffigen --config ffigen.yaml
\ No newline at end of file

From 3a61bae8c74b0cfb3621a4b39be3378df4fa6de5 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 1 Aug 2023 17:07:44 -0600
Subject: [PATCH 03/49] ffigen yaml

---
 ffigen.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ffigen.yaml b/ffigen.yaml
index cb2140b..27f6d9f 100644
--- a/ffigen.yaml
+++ b/ffigen.yaml
@@ -7,9 +7,9 @@ description: |
 output: 'lib/frostdart_bindings_generated.dart'
 headers:
   entry-points:
-    - 'src/frostdart.h'
+    - 'src/serai/hrf/header.h'
   include-directives:
-    - 'src/frostdart.h'
+    - 'src/serai/hrf/header.h'
 preamble: |
   // ignore_for_file: always_specify_types
   // ignore_for_file: camel_case_types

From 9996b175673fc6c16286a9887e4a146709832f76 Mon Sep 17 00:00:00 2001
From: Josh Babb <sneurlax@gmail.com>
Date: Wed, 2 Aug 2023 11:40:30 -0500
Subject: [PATCH 04/49] update serai submodule to 1674b217 Various tweaks to
 bindings

---
 src/serai | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serai b/src/serai
index 5d4632b..1674b21 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 5d4632bace0df2c140a1bbbb2ba487de967fa8f3
+Subproject commit 1674b21712a87297bf30c291163a21e6158212f7

From a71f1259d45d36e29ce393cd58000744031e7b7c Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 2 Aug 2023 11:28:49 -0600
Subject: [PATCH 05/49] somewhat "working" linux build

---
 example/lib/main.dart                      |  33 +-
 example/pubspec.lock                       |   8 +
 lib/frostdart.dart                         | 149 +---
 lib/frostdart_bindings_generated.dart      | 850 ++++++++++++++++++++-
 linux/CMakeLists.txt                       | 147 +++-
 linux/frostdart_plugin.cc                  |  70 ++
 linux/include/frostdart/frostdart_plugin.h |  26 +
 pubspec.yaml                               |   2 +-
 scripts/linux/build_all.sh                 |   5 +-
 src/CMakeLists.txt                         | 154 +++-
 src/frostdart.c                            |  23 -
 src/frostdart.h                            |  30 -
 12 files changed, 1265 insertions(+), 232 deletions(-)
 create mode 100644 linux/frostdart_plugin.cc
 create mode 100644 linux/include/frostdart/frostdart_plugin.h
 delete mode 100644 src/frostdart.c
 delete mode 100644 src/frostdart.h

diff --git a/example/lib/main.dart b/example/lib/main.dart
index acb94df..7c18c59 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,7 +1,6 @@
 import 'package:flutter/material.dart';
-import 'dart:async';
-
 import 'package:frostdart/frostdart.dart' as frostdart;
+import 'package:frostdart/frostdart_bindings_generated.dart';
 
 void main() {
   runApp(const MyApp());
@@ -15,14 +14,19 @@ class MyApp extends StatefulWidget {
 }
 
 class _MyAppState extends State<MyApp> {
-  late int sumResult;
-  late Future<int> sumAsyncResult;
+  late CResult_MultisigConfigRes sumResult;
+
+  String name = "REKT";
 
   @override
   void initState() {
     super.initState();
-    sumResult = frostdart.sum(1, 2);
-    sumAsyncResult = frostdart.sumAsync(3, 4);
+    sumResult = frostdart.newMultisigConfig(
+        name: "Name AAAAAA",
+        threshold: 3,
+        participants: ["jimmy", "john", "toby"]);
+
+    // name = frostdart.multisigName(configRes: sumResult.value.ref);
   }
 
   @override
@@ -47,22 +51,15 @@ class _MyAppState extends State<MyApp> {
                 ),
                 spacerSmall,
                 Text(
-                  'sum(1, 2) = $sumResult',
+                  'Type of result: ${sumResult.runtimeType}',
                   style: textStyle,
                   textAlign: TextAlign.center,
                 ),
                 spacerSmall,
-                FutureBuilder<int>(
-                  future: sumAsyncResult,
-                  builder: (BuildContext context, AsyncSnapshot<int> value) {
-                    final displayValue =
-                        (value.hasData) ? value.data : 'loading';
-                    return Text(
-                      'await sumAsync(3, 4) = $displayValue',
-                      style: textStyle,
-                      textAlign: TextAlign.center,
-                    );
-                  },
+                Text(
+                  'name: $name',
+                  style: textStyle,
+                  textAlign: TextAlign.center,
                 ),
               ],
             ),
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 7725cd4..d8c9eef 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -57,6 +57,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
+  ffi:
+    dependency: transitive
+    description:
+      name: ffi
+      sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.2"
   flutter:
     dependency: "direct main"
     description: flutter
diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 873f126..cebefca 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -1,50 +1,21 @@
-
-import 'dart:async';
-import 'dart:ffi';
+import 'dart:ffi' as ffi;
 import 'dart:io';
-import 'dart:isolate';
-
-import 'frostdart_bindings_generated.dart';
 
-/// A very short-lived native function.
-///
-/// For very short-lived functions, it is fine to call them on the main isolate.
-/// They will block the Dart execution while running the native function, so
-/// only do this for native functions which are guaranteed to be short-lived.
-int sum(int a, int b) => _bindings.sum(a, b);
-
-/// A longer lived native function, which occupies the thread calling it.
-///
-/// Do not call these kind of native functions in the main isolate. They will
-/// block Dart execution. This will cause dropped frames in Flutter applications.
-/// Instead, call these native functions on a separate isolate.
-///
-/// Modify this to suit your own use case. Example use cases:
-///
-/// 1. Reuse a single isolate for various different kinds of requests.
-/// 2. Use multiple helper isolates for parallel execution.
-Future<int> sumAsync(int a, int b) async {
-  final SendPort helperIsolateSendPort = await _helperIsolateSendPort;
-  final int requestId = _nextSumRequestId++;
-  final _SumRequest request = _SumRequest(requestId, a, b);
-  final Completer<int> completer = Completer<int>();
-  _sumRequests[requestId] = completer;
-  helperIsolateSendPort.send(request);
-  return completer.future;
-}
+import 'package:ffi/ffi.dart';
+import 'package:frostdart/frostdart_bindings_generated.dart';
 
 const String _libName = 'frostdart';
 
 /// The dynamic library in which the symbols for [FrostdartBindings] can be found.
-final DynamicLibrary _dylib = () {
+final ffi.DynamicLibrary _dylib = () {
   if (Platform.isMacOS || Platform.isIOS) {
-    return DynamicLibrary.open('$_libName.framework/$_libName');
+    return ffi.DynamicLibrary.open('$_libName.framework/$_libName');
   }
   if (Platform.isAndroid || Platform.isLinux) {
-    return DynamicLibrary.open('lib$_libName.so');
+    return ffi.DynamicLibrary.open('$_libName.so');
   }
   if (Platform.isWindows) {
-    return DynamicLibrary.open('$_libName.dll');
+    return ffi.DynamicLibrary.open('$_libName.dll');
   }
   throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
 }();
@@ -52,80 +23,40 @@ final DynamicLibrary _dylib = () {
 /// The bindings to the native functions in [_dylib].
 final FrostdartBindings _bindings = FrostdartBindings(_dylib);
 
-
-/// A request to compute `sum`.
-///
-/// Typically sent from one isolate to another.
-class _SumRequest {
-  final int id;
-  final int a;
-  final int b;
-
-  const _SumRequest(this.id, this.a, this.b);
+CResult_MultisigConfigRes newMultisigConfig({
+  required String name,
+  required int threshold,
+  required List<String> participants,
+}) {
+  ffi.Pointer<ffi.Uint8> multisigName = name.toNativeUtf8().cast<ffi.Uint8>();
+
+  final joined = participants.join();
+  ffi.Pointer<ffi.Uint8> parts = joined.toNativeUtf8().cast<ffi.Uint8>();
+
+  ffi.Pointer<StringView> participantsPointer = calloc<StringView>();
+  participantsPointer.ref.ptr = parts;
+  participantsPointer.ref.len = joined.length;
+
+  final result = _bindings.new_multisig_config(
+    multisigName,
+    name.length,
+    threshold,
+    participantsPointer,
+    participants.length,
+  );
+
+  calloc.free(multisigName);
+  calloc.free(parts);
+  calloc.free(participantsPointer);
+
+  return result;
 }
 
-/// A response with the result of `sum`.
-///
-/// Typically sent from one isolate to another.
-class _SumResponse {
-  final int id;
-  final int result;
-
-  const _SumResponse(this.id, this.result);
-}
+String multisigName({required MultisigConfigRes configRes}) {
+  final result = _bindings.multisig_name(configRes.config);
 
-/// Counter to identify [_SumRequest]s and [_SumResponse]s.
-int _nextSumRequestId = 0;
+  final bytes = result.ptr.asTypedList(result.len);
+  final String name = String.fromCharCodes(bytes);
 
-/// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request.
-final Map<int, Completer<int>> _sumRequests = <int, Completer<int>>{};
-
-/// The SendPort belonging to the helper isolate.
-Future<SendPort> _helperIsolateSendPort = () async {
-  // The helper isolate is going to send us back a SendPort, which we want to
-  // wait for.
-  final Completer<SendPort> completer = Completer<SendPort>();
-
-  // Receive port on the main isolate to receive messages from the helper.
-  // We receive two types of messages:
-  // 1. A port to send messages on.
-  // 2. Responses to requests we sent.
-  final ReceivePort receivePort = ReceivePort()
-    ..listen((dynamic data) {
-      if (data is SendPort) {
-        // The helper isolate sent us the port on which we can sent it requests.
-        completer.complete(data);
-        return;
-      }
-      if (data is _SumResponse) {
-        // The helper isolate sent us a response to a request we sent.
-        final Completer<int> completer = _sumRequests[data.id]!;
-        _sumRequests.remove(data.id);
-        completer.complete(data.result);
-        return;
-      }
-      throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
-    });
-
-  // Start the helper isolate.
-  await Isolate.spawn((SendPort sendPort) async {
-    final ReceivePort helperReceivePort = ReceivePort()
-      ..listen((dynamic data) {
-        // On the helper isolate listen to requests and respond to them.
-        if (data is _SumRequest) {
-          final int result = _bindings.sum_long_running(data.a, data.b);
-          final _SumResponse response = _SumResponse(data.id, result);
-          sendPort.send(response);
-          return;
-        }
-        throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
-      });
-
-    // Send the port to the main isolate on which we can receive requests.
-    sendPort.send(helperReceivePort.sendPort);
-  }, receivePort.sendPort);
-
-  // Wait until the helper isolate has sent us back the SendPort on which we
-  // can start sending requests.
-  return completer.future;
-}();
+  return name;
+}
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 4a3bebe..e8e5d4b 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -5,6 +5,7 @@
 // AUTO GENERATED FILE, DO NOT EDIT.
 //
 // Generated by `package:ffigen`.
+// ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
 /// Bindings for `src/frostdart.h`.
@@ -26,44 +27,831 @@ class FrostdartBindings {
           lookup)
       : _lookup = lookup;
 
-  /// A very short-lived native function.
-  ///
-  /// For very short-lived functions, it is fine to call them on the main isolate.
-  /// They will block the Dart execution while running the native function, so
-  /// only do this for native functions which are guaranteed to be short-lived.
-  int sum(
-    int a,
-    int b,
+  void free_owned_string(
+    OwnedString self,
   ) {
-    return _sum(
-      a,
-      b,
+    return _free_owned_string(
+      self,
     );
   }
 
-  late final _sumPtr =
-      _lookup<ffi.NativeFunction<ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr)>>(
-          'sum');
-  late final _sum = _sumPtr.asFunction<int Function(int, int)>();
+  late final _free_owned_stringPtr =
+      _lookup<ffi.NativeFunction<ffi.Void Function(OwnedString)>>(
+          'free_owned_string');
+  late final _free_owned_string =
+      _free_owned_stringPtr.asFunction<void Function(OwnedString)>();
 
-  /// A longer lived native function, which occupies the thread calling it.
-  ///
-  /// Do not call these kind of native functions in the main isolate. They will
-  /// block Dart execution. This will cause dropped frames in Flutter applications.
-  /// Instead, call these native functions on a separate isolate.
-  int sum_long_running(
-    int a,
-    int b,
+  StringView multisig_name(
+    ffi.Pointer<MultisigConfig> self,
   ) {
-    return _sum_long_running(
-      a,
-      b,
+    return _multisig_name(
+      self,
     );
   }
 
-  late final _sum_long_runningPtr =
-      _lookup<ffi.NativeFunction<ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr)>>(
-          'sum_long_running');
-  late final _sum_long_running =
-      _sum_long_runningPtr.asFunction<int Function(int, int)>();
+  late final _multisig_namePtr = _lookup<
+          ffi.NativeFunction<StringView Function(ffi.Pointer<MultisigConfig>)>>(
+      'multisig_name');
+  late final _multisig_name = _multisig_namePtr
+      .asFunction<StringView Function(ffi.Pointer<MultisigConfig>)>();
+
+  int multisig_threshold(
+    ffi.Pointer<MultisigConfig> self,
+  ) {
+    return _multisig_threshold(
+      self,
+    );
+  }
+
+  late final _multisig_thresholdPtr = _lookup<
+          ffi.NativeFunction<ffi.Uint16 Function(ffi.Pointer<MultisigConfig>)>>(
+      'multisig_threshold');
+  late final _multisig_threshold = _multisig_thresholdPtr
+      .asFunction<int Function(ffi.Pointer<MultisigConfig>)>();
+
+  int multisig_participants(
+    ffi.Pointer<MultisigConfig> self,
+  ) {
+    return _multisig_participants(
+      self,
+    );
+  }
+
+  late final _multisig_participantsPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.UintPtr Function(
+              ffi.Pointer<MultisigConfig>)>>('multisig_participants');
+  late final _multisig_participants = _multisig_participantsPtr
+      .asFunction<int Function(ffi.Pointer<MultisigConfig>)>();
+
+  StringView multisig_participant(
+    ffi.Pointer<MultisigConfig> self,
+    int i,
+  ) {
+    return _multisig_participant(
+      self,
+      i,
+    );
+  }
+
+  late final _multisig_participantPtr = _lookup<
+      ffi.NativeFunction<
+          StringView Function(ffi.Pointer<MultisigConfig>,
+              ffi.UintPtr)>>('multisig_participant');
+  late final _multisig_participant = _multisig_participantPtr
+      .asFunction<StringView Function(ffi.Pointer<MultisigConfig>, int)>();
+
+  ffi.Pointer<ffi.Uint8> multisig_salt(
+    ffi.Pointer<MultisigConfig> self,
+  ) {
+    return _multisig_salt(
+      self,
+    );
+  }
+
+  late final _multisig_saltPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ffi.Uint8> Function(
+              ffi.Pointer<MultisigConfig>)>>('multisig_salt');
+  late final _multisig_salt = _multisig_saltPtr.asFunction<
+      ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<MultisigConfig>)>();
+
+  ffi.Pointer<MultisigConfig> multisig_config(
+    ffi.Pointer<MultisigConfigWithName> self,
+  ) {
+    return _multisig_config(
+      self,
+    );
+  }
+
+  late final _multisig_configPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<MultisigConfig> Function(
+              ffi.Pointer<MultisigConfigWithName>)>>('multisig_config');
+  late final _multisig_config = _multisig_configPtr.asFunction<
+      ffi.Pointer<MultisigConfig> Function(
+          ffi.Pointer<MultisigConfigWithName>)>();
+
+  StringView multisig_my_name(
+    ffi.Pointer<MultisigConfigWithName> self,
+  ) {
+    return _multisig_my_name(
+      self,
+    );
+  }
+
+  late final _multisig_my_namePtr = _lookup<
+      ffi.NativeFunction<
+          StringView Function(
+              ffi.Pointer<MultisigConfigWithName>)>>('multisig_my_name');
+  late final _multisig_my_name = _multisig_my_namePtr
+      .asFunction<StringView Function(ffi.Pointer<MultisigConfigWithName>)>();
+
+  CResult_MultisigConfigRes new_multisig_config(
+    ffi.Pointer<ffi.Uint8> multisig_name,
+    int multisig_name_len,
+    int threshold,
+    ffi.Pointer<StringView> participants,
+    int participants_len,
+  ) {
+    return _new_multisig_config(
+      multisig_name,
+      multisig_name_len,
+      threshold,
+      participants,
+      participants_len,
+    );
+  }
+
+  late final _new_multisig_configPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_MultisigConfigRes Function(
+              ffi.Pointer<ffi.Uint8>,
+              ffi.UintPtr,
+              ffi.Uint16,
+              ffi.Pointer<StringView>,
+              ffi.Uint16)>>('new_multisig_config');
+  late final _new_multisig_config = _new_multisig_configPtr.asFunction<
+      CResult_MultisigConfigRes Function(
+          ffi.Pointer<ffi.Uint8>, int, int, ffi.Pointer<StringView>, int)>();
+
+  CResult_MultisigConfig decode_multisig_config(
+    StringView config,
+  ) {
+    return _decode_multisig_config(
+      config,
+    );
+  }
+
+  late final _decode_multisig_configPtr =
+      _lookup<ffi.NativeFunction<CResult_MultisigConfig Function(StringView)>>(
+          'decode_multisig_config');
+  late final _decode_multisig_config = _decode_multisig_configPtr
+      .asFunction<CResult_MultisigConfig Function(StringView)>();
+
+  CResult_StartKeyGenRes start_key_gen(
+    ffi.Pointer<MultisigConfig> config,
+    StringView my_name,
+    int language,
+  ) {
+    return _start_key_gen(
+      config,
+      my_name,
+      language,
+    );
+  }
+
+  late final _start_key_genPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_StartKeyGenRes Function(ffi.Pointer<MultisigConfig>,
+              StringView, ffi.Uint16)>>('start_key_gen');
+  late final _start_key_gen = _start_key_genPtr.asFunction<
+      CResult_StartKeyGenRes Function(
+          ffi.Pointer<MultisigConfig>, StringView, int)>();
+
+  CResult_SecretSharesRes get_secret_shares(
+    ffi.Pointer<MultisigConfigWithName> config,
+    int language,
+    StringView seed,
+    ffi.Pointer<SecretShareMachineWrapper> machine,
+    ffi.Pointer<StringView> commitments,
+    int commitments_len,
+  ) {
+    return _get_secret_shares(
+      config,
+      language,
+      seed,
+      machine,
+      commitments,
+      commitments_len,
+    );
+  }
+
+  late final _get_secret_sharesPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_SecretSharesRes Function(
+              ffi.Pointer<MultisigConfigWithName>,
+              ffi.Uint16,
+              StringView,
+              ffi.Pointer<SecretShareMachineWrapper>,
+              ffi.Pointer<StringView>,
+              ffi.UintPtr)>>('get_secret_shares');
+  late final _get_secret_shares = _get_secret_sharesPtr.asFunction<
+      CResult_SecretSharesRes Function(
+          ffi.Pointer<MultisigConfigWithName>,
+          int,
+          StringView,
+          ffi.Pointer<SecretShareMachineWrapper>,
+          ffi.Pointer<StringView>,
+          int)>();
+
+  CResult_KeyGenRes complete_key_gen(
+    ffi.Pointer<MultisigConfigWithName> config,
+    SecretSharesRes machine_and_commitments,
+    ffi.Pointer<StringView> shares,
+    int shares_len,
+  ) {
+    return _complete_key_gen(
+      config,
+      machine_and_commitments,
+      shares,
+      shares_len,
+    );
+  }
+
+  late final _complete_key_genPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_KeyGenRes Function(
+              ffi.Pointer<MultisigConfigWithName>,
+              SecretSharesRes,
+              ffi.Pointer<StringView>,
+              ffi.UintPtr)>>('complete_key_gen');
+  late final _complete_key_gen = _complete_key_genPtr.asFunction<
+      CResult_KeyGenRes Function(ffi.Pointer<MultisigConfigWithName>,
+          SecretSharesRes, ffi.Pointer<StringView>, int)>();
+
+  OwnedString serialize_keys(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+  ) {
+    return _serialize_keys(
+      keys,
+    );
+  }
+
+  late final _serialize_keysPtr = _lookup<
+      ffi.NativeFunction<
+          OwnedString Function(
+              ffi.Pointer<ThresholdKeysWrapper>)>>('serialize_keys');
+  late final _serialize_keys = _serialize_keysPtr
+      .asFunction<OwnedString Function(ffi.Pointer<ThresholdKeysWrapper>)>();
+
+  CResult_ThresholdKeysWrapper deserialize_keys(
+    StringView keys,
+  ) {
+    return _deserialize_keys(
+      keys,
+    );
+  }
+
+  late final _deserialize_keysPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_ThresholdKeysWrapper Function(
+              StringView)>>('deserialize_keys');
+  late final _deserialize_keys = _deserialize_keysPtr
+      .asFunction<CResult_ThresholdKeysWrapper Function(StringView)>();
+
+  ffi.Pointer<ffi.Uint8> output_hash(
+    ffi.Pointer<OwnedPortableOutput> self,
+  ) {
+    return _output_hash(
+      self,
+    );
+  }
+
+  late final _output_hashPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ffi.Uint8> Function(
+              ffi.Pointer<OwnedPortableOutput>)>>('output_hash');
+  late final _output_hash = _output_hashPtr.asFunction<
+      ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<OwnedPortableOutput>)>();
+
+  int output_vout(
+    ffi.Pointer<OwnedPortableOutput> self,
+  ) {
+    return _output_vout(
+      self,
+    );
+  }
+
+  late final _output_voutPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint32 Function(
+              ffi.Pointer<OwnedPortableOutput>)>>('output_vout');
+  late final _output_vout = _output_voutPtr
+      .asFunction<int Function(ffi.Pointer<OwnedPortableOutput>)>();
+
+  int output_value(
+    ffi.Pointer<OwnedPortableOutput> self,
+  ) {
+    return _output_value(
+      self,
+    );
+  }
+
+  late final _output_valuePtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint64 Function(
+              ffi.Pointer<OwnedPortableOutput>)>>('output_value');
+  late final _output_value = _output_valuePtr
+      .asFunction<int Function(ffi.Pointer<OwnedPortableOutput>)>();
+
+  int output_script_pubkey_len(
+    ffi.Pointer<OwnedPortableOutput> self,
+  ) {
+    return _output_script_pubkey_len(
+      self,
+    );
+  }
+
+  late final _output_script_pubkey_lenPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.UintPtr Function(
+              ffi.Pointer<OwnedPortableOutput>)>>('output_script_pubkey_len');
+  late final _output_script_pubkey_len = _output_script_pubkey_lenPtr
+      .asFunction<int Function(ffi.Pointer<OwnedPortableOutput>)>();
+
+  ffi.Pointer<ffi.Uint8> output_script_pubkey(
+    ffi.Pointer<OwnedPortableOutput> self,
+  ) {
+    return _output_script_pubkey(
+      self,
+    );
+  }
+
+  late final _output_script_pubkeyPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ffi.Uint8> Function(
+              ffi.Pointer<OwnedPortableOutput>)>>('output_script_pubkey');
+  late final _output_script_pubkey = _output_script_pubkeyPtr.asFunction<
+      ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<OwnedPortableOutput>)>();
+
+  int sign_inputs(
+    ffi.Pointer<SignConfig> self,
+  ) {
+    return _sign_inputs(
+      self,
+    );
+  }
+
+  late final _sign_inputsPtr = _lookup<
+          ffi.NativeFunction<ffi.UintPtr Function(ffi.Pointer<SignConfig>)>>(
+      'sign_inputs');
+  late final _sign_inputs =
+      _sign_inputsPtr.asFunction<int Function(ffi.Pointer<SignConfig>)>();
+
+  ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> sign_input(
+    ffi.Pointer<SignConfig> self,
+    int i,
+  ) {
+    return _sign_input(
+      self,
+      i,
+    );
+  }
+
+  late final _sign_inputPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> Function(
+              ffi.Pointer<SignConfig>, ffi.UintPtr)>>('sign_input');
+  late final _sign_input = _sign_inputPtr.asFunction<
+      ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> Function(
+          ffi.Pointer<SignConfig>, int)>();
+
+  int sign_payments(
+    ffi.Pointer<SignConfig> self,
+  ) {
+    return _sign_payments(
+      self,
+    );
+  }
+
+  late final _sign_paymentsPtr = _lookup<
+          ffi.NativeFunction<ffi.UintPtr Function(ffi.Pointer<SignConfig>)>>(
+      'sign_payments');
+  late final _sign_payments =
+      _sign_paymentsPtr.asFunction<int Function(ffi.Pointer<SignConfig>)>();
+
+  StringView sign_payment_address(
+    ffi.Pointer<SignConfig> self,
+    int i,
+  ) {
+    return _sign_payment_address(
+      self,
+      i,
+    );
+  }
+
+  late final _sign_payment_addressPtr = _lookup<
+      ffi.NativeFunction<
+          StringView Function(
+              ffi.Pointer<SignConfig>, ffi.UintPtr)>>('sign_payment_address');
+  late final _sign_payment_address = _sign_payment_addressPtr
+      .asFunction<StringView Function(ffi.Pointer<SignConfig>, int)>();
+
+  int sign_payment_amount(
+    ffi.Pointer<SignConfig> self,
+    int i,
+  ) {
+    return _sign_payment_amount(
+      self,
+      i,
+    );
+  }
+
+  late final _sign_payment_amountPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint64 Function(
+              ffi.Pointer<SignConfig>, ffi.UintPtr)>>('sign_payment_amount');
+  late final _sign_payment_amount = _sign_payment_amountPtr
+      .asFunction<int Function(ffi.Pointer<SignConfig>, int)>();
+
+  StringView sign_change(
+    ffi.Pointer<SignConfig> self,
+  ) {
+    return _sign_change(
+      self,
+    );
+  }
+
+  late final _sign_changePtr =
+      _lookup<ffi.NativeFunction<StringView Function(ffi.Pointer<SignConfig>)>>(
+          'sign_change');
+  late final _sign_change = _sign_changePtr
+      .asFunction<StringView Function(ffi.Pointer<SignConfig>)>();
+
+  int sign_fee_per_weight(
+    ffi.Pointer<SignConfig> self,
+  ) {
+    return _sign_fee_per_weight(
+      self,
+    );
+  }
+
+  late final _sign_fee_per_weightPtr =
+      _lookup<ffi.NativeFunction<ffi.Uint64 Function(ffi.Pointer<SignConfig>)>>(
+          'sign_fee_per_weight');
+  late final _sign_fee_per_weight = _sign_fee_per_weightPtr
+      .asFunction<int Function(ffi.Pointer<SignConfig>)>();
+
+  CResult_SignConfigRes new_sign_config(
+    int network,
+    ffi.Pointer<PortableOutput> outputs,
+    int outputs_len,
+    int payments,
+    ffi.Pointer<StringView> payment_addresses,
+    ffi.Pointer<ffi.Uint64> payment_amounts,
+    StringView change,
+    int fee_per_weight,
+  ) {
+    return _new_sign_config(
+      network,
+      outputs,
+      outputs_len,
+      payments,
+      payment_addresses,
+      payment_amounts,
+      change,
+      fee_per_weight,
+    );
+  }
+
+  late final _new_sign_configPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_SignConfigRes Function(
+              ffi.Int32,
+              ffi.Pointer<PortableOutput>,
+              ffi.UintPtr,
+              ffi.UintPtr,
+              ffi.Pointer<StringView>,
+              ffi.Pointer<ffi.Uint64>,
+              StringView,
+              ffi.Uint64)>>('new_sign_config');
+  late final _new_sign_config = _new_sign_configPtr.asFunction<
+      CResult_SignConfigRes Function(int, ffi.Pointer<PortableOutput>, int, int,
+          ffi.Pointer<StringView>, ffi.Pointer<ffi.Uint64>, StringView, int)>();
+
+  CResult_SignConfig decode_sign_config(
+    int network,
+    StringView encoded,
+  ) {
+    return _decode_sign_config(
+      network,
+      encoded,
+    );
+  }
+
+  late final _decode_sign_configPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_SignConfig Function(
+              ffi.Int32, StringView)>>('decode_sign_config');
+  late final _decode_sign_config = _decode_sign_configPtr
+      .asFunction<CResult_SignConfig Function(int, StringView)>();
+
+  CResult_AttemptSignRes attempt_sign(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+    ffi.Pointer<ffi.Pointer<SignConfig>> config,
+  ) {
+    return _attempt_sign(
+      keys,
+      config,
+    );
+  }
+
+  late final _attempt_signPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_AttemptSignRes Function(ffi.Pointer<ThresholdKeysWrapper>,
+              ffi.Pointer<ffi.Pointer<SignConfig>>)>>('attempt_sign');
+  late final _attempt_sign = _attempt_signPtr.asFunction<
+      CResult_AttemptSignRes Function(ffi.Pointer<ThresholdKeysWrapper>,
+          ffi.Pointer<ffi.Pointer<SignConfig>>)>();
+
+  CResult_ContinueSignRes continue_sign(
+    ffi.Pointer<TransactionSignMachineWrapper> machine,
+    ffi.Pointer<StringView> preprocesses,
+    int preprocesses_len,
+  ) {
+    return _continue_sign(
+      machine,
+      preprocesses,
+      preprocesses_len,
+    );
+  }
+
+  late final _continue_signPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_ContinueSignRes Function(
+              ffi.Pointer<TransactionSignMachineWrapper>,
+              ffi.Pointer<StringView>,
+              ffi.UintPtr)>>('continue_sign');
+  late final _continue_sign = _continue_signPtr.asFunction<
+      CResult_ContinueSignRes Function(
+          ffi.Pointer<TransactionSignMachineWrapper>,
+          ffi.Pointer<StringView>,
+          int)>();
+
+  CResult_OwnedString complete_sign(
+    ffi.Pointer<TransactionSignatureMachineWrapper> machine,
+    ffi.Pointer<StringView> shares,
+    int shares_len,
+  ) {
+    return _complete_sign(
+      machine,
+      shares,
+      shares_len,
+    );
+  }
+
+  late final _complete_signPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_OwnedString Function(
+              ffi.Pointer<TransactionSignatureMachineWrapper>,
+              ffi.Pointer<StringView>,
+              ffi.UintPtr)>>('complete_sign');
+  late final _complete_sign = _complete_signPtr.asFunction<
+      CResult_OwnedString Function(
+          ffi.Pointer<TransactionSignatureMachineWrapper>,
+          ffi.Pointer<StringView>,
+          int)>();
+}
+
+abstract class Network {
+  static const int Mainnet = 0;
+  static const int Testnet = 1;
+  static const int Regtest = 2;
+}
+
+final class KeyMachineWrapper extends ffi.Opaque {}
+
+final class MultisigConfig extends ffi.Opaque {}
+
+final class OwnedPortableOutput extends ffi.Opaque {}
+
+final class SecretShareMachineWrapper extends ffi.Opaque {}
+
+final class SignConfig extends ffi.Opaque {}
+
+final class RustString extends ffi.Opaque {}
+
+final class ThresholdKeysWrapper extends ffi.Opaque {}
+
+final class TransactionSignMachineWrapper extends ffi.Opaque {}
+
+final class TransactionSignatureMachineWrapper extends ffi.Opaque {}
+
+final class Vec_u8 extends ffi.Opaque {}
+
+final class OwnedString extends ffi.Struct {
+  external ffi.Pointer<RustString> str_box;
+
+  external ffi.Pointer<ffi.Uint8> ptr;
+
+  @ffi.UintPtr()
+  external int len;
+}
+
+final class StringView extends ffi.Struct {
+  external ffi.Pointer<ffi.Uint8> ptr;
+
+  @ffi.UintPtr()
+  external int len;
+}
+
+final class MultisigConfigWithName extends ffi.Struct {
+  external ffi.Pointer<MultisigConfig> config;
+
+  external ffi.Pointer<RustString> my_name;
+}
+
+final class MultisigConfigRes extends ffi.Struct {
+  external ffi.Pointer<MultisigConfig> config;
+
+  external OwnedString encoded;
+}
+
+final class CResult_MultisigConfigRes extends ffi.Struct {
+  external ffi.Pointer<MultisigConfigRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class CResult_MultisigConfig extends ffi.Struct {
+  external ffi.Pointer<MultisigConfig> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class StartKeyGenRes extends ffi.Struct {
+  external OwnedString seed;
+
+  external ffi.Pointer<MultisigConfigWithName> config;
+
+  external ffi.Pointer<SecretShareMachineWrapper> machine;
+
+  external OwnedString commitments;
+}
+
+final class CResult_StartKeyGenRes extends ffi.Struct {
+  external ffi.Pointer<StartKeyGenRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class SecretSharesRes extends ffi.Struct {
+  external ffi.Pointer<KeyMachineWrapper> machine;
+
+  external ffi.Pointer<Vec_u8> internal_commitments;
+
+  external OwnedString shares;
+}
+
+final class CResult_SecretSharesRes extends ffi.Struct {
+  external ffi.Pointer<SecretSharesRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class KeyGenRes extends ffi.Struct {
+  @ffi.Array.multi([32])
+  external ffi.Array<ffi.Uint8> multisig_id;
+
+  external ffi.Pointer<ThresholdKeysWrapper> keys;
+
+  external OwnedString recovery;
 }
+
+final class CResult_KeyGenRes extends ffi.Struct {
+  external ffi.Pointer<KeyGenRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class CResult_ThresholdKeysWrapper extends ffi.Struct {
+  external ffi.Pointer<ThresholdKeysWrapper> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class SignConfigRes extends ffi.Struct {
+  external ffi.Pointer<SignConfig> config;
+
+  external OwnedString encoded;
+}
+
+final class CResult_SignConfigRes extends ffi.Struct {
+  external ffi.Pointer<SignConfigRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class PortableOutput extends ffi.Struct {
+  @ffi.Array.multi([32])
+  external ffi.Array<ffi.Uint8> hash;
+
+  @ffi.Uint32()
+  external int vout;
+
+  @ffi.Uint64()
+  external int value;
+
+  external ffi.Pointer<ffi.Uint8> script_pubkey;
+
+  @ffi.UintPtr()
+  external int script_pubkey_len;
+}
+
+final class CResult_SignConfig extends ffi.Struct {
+  external ffi.Pointer<SignConfig> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class AttemptSignRes extends ffi.Struct {
+  external ffi.Pointer<TransactionSignMachineWrapper> machine;
+
+  external OwnedString preprocess;
+}
+
+final class CResult_AttemptSignRes extends ffi.Struct {
+  external ffi.Pointer<AttemptSignRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class ContinueSignRes extends ffi.Struct {
+  external ffi.Pointer<TransactionSignatureMachineWrapper> machine;
+
+  external OwnedString preprocess;
+}
+
+final class CResult_ContinueSignRes extends ffi.Struct {
+  external ffi.Pointer<ContinueSignRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class CResult_OwnedString extends ffi.Struct {
+  external ffi.Pointer<OwnedString> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+const int LANGUAGE_ENGLISH = 1;
+
+const int LANGUAGE_CHINESE_SIMPLIFIED = 2;
+
+const int LANGUAGE_CHINESE_TRADITIONAL = 3;
+
+const int LANGUAGE_FRENCH = 4;
+
+const int LANGUAGE_ITALIAN = 5;
+
+const int LANGUAGE_JAPANESE = 6;
+
+const int LANGUAGE_KOREAN = 7;
+
+const int LANGUAGE_SPANISH = 8;
+
+const int UNKNOWN_ERROR = 101;
+
+const int INVALID_ENCODING_ERROR = 102;
+
+const int INVALID_PARTICIPANT_ERROR = 103;
+
+const int INVALID_SHARE_ERROR = 104;
+
+const int ZERO_PARAMETER_ERROR = 201;
+
+const int INVALID_THRESHOLD_ERROR = 202;
+
+const int INVALID_NAME_ERROR = 203;
+
+const int UNKNOWN_LANGUAGE_ERROR = 204;
+
+const int INVALID_SEED_ERROR = 205;
+
+const int INVALID_AMOUNT_OF_COMMITMENTS_ERROR = 206;
+
+const int INVALID_COMMITMENTS_ERROR = 207;
+
+const int INVALID_AMOUNT_OF_SHARES_ERROR = 208;
+
+const int INVALID_OUTPUT_ERROR = 301;
+
+const int INVALID_ADDRESS_ERROR = 302;
+
+const int INVALID_NETWORK_ERROR = 303;
+
+const int NO_INPUTS_ERROR = 304;
+
+const int NO_OUTPUTS_ERROR = 305;
+
+const int DUST_ERROR = 306;
+
+const int NOT_ENOUGH_FUNDS_ERROR = 307;
+
+const int TOO_LARGE_TRANSACTION_ERROR = 308;
+
+const int WRONG_KEYS_ERROR = 309;
+
+const int INVALID_PREPROCESS_ERROR = 310;
diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt
index 202d94d..2e72324 100644
--- a/linux/CMakeLists.txt
+++ b/linux/CMakeLists.txt
@@ -7,16 +7,147 @@ cmake_minimum_required(VERSION 3.10)
 set(PROJECT_NAME "frostdart")
 project(${PROJECT_NAME} LANGUAGES CXX)
 
-# Invoke the build for native code shared with the other target platforms.
-# This can be changed to accommodate different builds.
-add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+# This value is used when generating builds using this plugin, so it must
+# not be changed.
+set(PLUGIN_NAME "frostdart_plugin")
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+    set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+    set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_TYPE "Debug" CACHE
+            STRING "Flutter build mode" FORCE)
+    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+            "Debug" "Profile" "Release")
+endif()
+
+# Define the plugin library target. Its name must not be changed (see comment
+# on PLUGIN_NAME above).
+#
+# Any new source files that you add to the plugin should be added here.
+add_library(${PLUGIN_NAME} SHARED
+        "frostdart_plugin.cc"
+        )
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+    target_compile_features(${TARGET} PUBLIC cxx_std_14)
+    target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+    target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
+    target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
+endfunction()
+
+# Apply a standard set of build settings that are configured in the
+# application-level CMakeLists.txt. This can be removed for plugins that want
+# full control over build settings.
+apply_standard_settings(${PLUGIN_NAME})
+
+# Symbols are hidden by default to reduce the chance of accidental conflicts
+# between plugins. This should not be removed; any symbols that should be
+# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
+set_target_properties(${PLUGIN_NAME} PROPERTIES
+        CXX_VISIBILITY_PRESET hidden)
+target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
+
+# Source include directories and library dependencies. Add any plugin-specific
+# dependencies here.
+target_include_directories(${PLUGIN_NAME} INTERFACE
+        "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
+target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
 
 # List of absolute paths to libraries that should be bundled with the plugin.
 # This list could contain prebuilt libraries, or libraries created by an
 # external build triggered from this build file.
 set(frostdart_bundled_libraries
-  # Defined in ../src/CMakeLists.txt.
-  # This can be changed to accommodate different builds.
-  $<TARGET_FILE:frostdart>
-  PARENT_SCOPE
-)
+        ""
+        PARENT_SCOPE
+        )
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+    set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+    set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_TYPE "Debug" CACHE
+            STRING "Flutter build mode" FORCE)
+    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+            "Debug" "Profile" "Release")
+endif()
+
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
+
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+        PROPERTIES
+        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+        )
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+#include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+    set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+  " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+        COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+        COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+        COMPONENT Runtime)
+
+install(FILES "${CMAKE_SOURCE_DIR}/../../scripts/linux/build/frostdart.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+        COMPONENT Runtime)
+
+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
+    install(FILES "${bundled_library}"
+            DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+            COMPONENT Runtime)
+endforeach(bundled_library)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+    install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+            COMPONENT Runtime)
+endif()
diff --git a/linux/frostdart_plugin.cc b/linux/frostdart_plugin.cc
new file mode 100644
index 0000000..0f25d52
--- /dev/null
+++ b/linux/frostdart_plugin.cc
@@ -0,0 +1,70 @@
+#include "include/frostdart/frostdart_plugin.h"
+
+#include <flutter_linux/flutter_linux.h>
+#include <gtk/gtk.h>
+#include <sys/utsname.h>
+
+#include <cstring>
+
+#define frostdart_PLUGIN(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), frostdart_plugin_get_type(), \
+                              FrostdartPlugin))
+
+struct _FrostdartPlugin {
+  GObject parent_instance;
+};
+
+G_DEFINE_TYPE(FrostdartPlugin, frostdart_plugin, g_object_get_type());
+
+// Called when a method call is received from Flutter.
+static void frostdart_plugin_handle_method_call(
+    FrostdartPlugin* self,
+    FlMethodCall* method_call) {
+  g_autoptr(FlMethodResponse) response = nullptr;
+
+  const gchar* method = fl_method_call_get_name(method_call);
+
+  if (strcmp(method, "getPlatformVersion") == 0) {
+    struct utsname uname_data = {};
+    uname(&uname_data);
+    g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
+    g_autoptr(FlValue) result = fl_value_new_string(version);
+    response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
+  } else {
+    response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
+  }
+
+  fl_method_call_respond(method_call, response, nullptr);
+}
+
+static void frostdart_plugin_dispose(GObject* object) {
+  G_OBJECT_CLASS(frostdart_plugin_parent_class)->dispose(object);
+}
+
+static void frostdart_plugin_class_init(FrostdartPluginClass* klass) {
+  G_OBJECT_CLASS(klass)->dispose = frostdart_plugin_dispose;
+}
+
+static void frostdart_plugin_init(FrostdartPlugin* self) {}
+
+static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
+                           gpointer user_data) {
+  FrostdartPlugin* plugin = frostdart_PLUGIN(user_data);
+  frostdart_plugin_handle_method_call(plugin, method_call);
+}
+
+void frostdart_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
+  FrostdartPlugin* plugin = frostdart_PLUGIN(
+      g_object_new(frostdart_plugin_get_type(), nullptr));
+
+  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
+  g_autoptr(FlMethodChannel) channel =
+      fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
+                            "frostdart",
+                            FL_METHOD_CODEC(codec));
+  fl_method_channel_set_method_call_handler(channel, method_call_cb,
+                                            g_object_ref(plugin),
+                                            g_object_unref);
+
+  g_object_unref(plugin);
+}
diff --git a/linux/include/frostdart/frostdart_plugin.h b/linux/include/frostdart/frostdart_plugin.h
new file mode 100644
index 0000000..e6d0544
--- /dev/null
+++ b/linux/include/frostdart/frostdart_plugin.h
@@ -0,0 +1,26 @@
+#ifndef FLUTTER_PLUGIN_FROSTDART_PLUGIN_H_
+#define FLUTTER_PLUGIN_FROSTDART_PLUGIN_H_
+
+#include <flutter_linux/flutter_linux.h>
+
+G_BEGIN_DECLS
+
+#ifdef FLUTTER_PLUGIN_IMPL
+#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
+#else
+#define FLUTTER_PLUGIN_EXPORT
+#endif
+
+typedef struct _FrostdartPlugin FrostdartPlugin;
+typedef struct {
+  GObjectClass parent_class;
+} FrostdartPluginClass;
+
+FLUTTER_PLUGIN_EXPORT GType frostdart_plugin_get_type();
+
+FLUTTER_PLUGIN_EXPORT void frostdart_plugin_register_with_registrar(
+    FlPluginRegistrar* registrar);
+
+G_END_DECLS
+
+#endif  // FLUTTER_PLUGIN_FLUTTER_FROSTDART_PLUGIN_H_
diff --git a/pubspec.yaml b/pubspec.yaml
index a417513..163cba7 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -8,12 +8,12 @@ environment:
   flutter: ">=3.10.0"
 
 dependencies:
+  ffi: ^2.0.1
   flutter:
     sdk: flutter
   plugin_platform_interface: ^2.0.2
 
 dev_dependencies:
-  ffi: ^2.0.1
   ffigen: ^9.0.1
   flutter_test:
     sdk: flutter
diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh
index 6403307..14d31c0 100755
--- a/scripts/linux/build_all.sh
+++ b/scripts/linux/build_all.sh
@@ -4,14 +4,13 @@ ROOT_DIR="$(pwd)/../.."
 
 mkdir -p build
 
-
 cd "$ROOT_DIR"/src/serai/hrf || exit
 if [ "$IS_ARM" = true ]  ; then
     echo "Building arm frostdart"
     cargo build --target aarch64-unknown-linux-gnu --release --lib
-    cp ../target/aarch64-unknown-linux-gnu/release/libfrostdart.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
+    cp ../target/aarch64-unknown-linux-gnu/release/libhrf_api.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
 else
     echo "Building x86_64 frostdart"
     cargo build --target x86_64-unknown-linux-gnu --release --lib
-    cp ../target/x86_64-unknown-linux-gnu/release/libfrostdart.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
+    cp ../target/x86_64-unknown-linux-gnu/release/libhrf_api.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
 fi
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3a6f510..2e72324 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,15 +3,151 @@
 # the plugin to fail to compile for some customers of the plugin.
 cmake_minimum_required(VERSION 3.10)
 
-project(frostdart_library VERSION 0.0.1 LANGUAGES C)
+# Project-level configuration.
+set(PROJECT_NAME "frostdart")
+project(${PROJECT_NAME} LANGUAGES CXX)
 
-add_library(frostdart SHARED
-  "frostdart.c"
-)
+# This value is used when generating builds using this plugin, so it must
+# not be changed.
+set(PLUGIN_NAME "frostdart_plugin")
 
-set_target_properties(frostdart PROPERTIES
-  PUBLIC_HEADER frostdart.h
-  OUTPUT_NAME "frostdart"
-)
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+    set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+    set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
 
-target_compile_definitions(frostdart PUBLIC DART_SHARED_LIB)
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_TYPE "Debug" CACHE
+            STRING "Flutter build mode" FORCE)
+    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+            "Debug" "Profile" "Release")
+endif()
+
+# Define the plugin library target. Its name must not be changed (see comment
+# on PLUGIN_NAME above).
+#
+# Any new source files that you add to the plugin should be added here.
+add_library(${PLUGIN_NAME} SHARED
+        "frostdart_plugin.cc"
+        )
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+    target_compile_features(${TARGET} PUBLIC cxx_std_14)
+    target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+    target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
+    target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
+endfunction()
+
+# Apply a standard set of build settings that are configured in the
+# application-level CMakeLists.txt. This can be removed for plugins that want
+# full control over build settings.
+apply_standard_settings(${PLUGIN_NAME})
+
+# Symbols are hidden by default to reduce the chance of accidental conflicts
+# between plugins. This should not be removed; any symbols that should be
+# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
+set_target_properties(${PLUGIN_NAME} PROPERTIES
+        CXX_VISIBILITY_PRESET hidden)
+target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
+
+# Source include directories and library dependencies. Add any plugin-specific
+# dependencies here.
+target_include_directories(${PLUGIN_NAME} INTERFACE
+        "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
+target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
+
+# List of absolute paths to libraries that should be bundled with the plugin.
+# This list could contain prebuilt libraries, or libraries created by an
+# external build triggered from this build file.
+set(frostdart_bundled_libraries
+        ""
+        PARENT_SCOPE
+        )
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+    set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+    set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_TYPE "Debug" CACHE
+            STRING "Flutter build mode" FORCE)
+    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+            "Debug" "Profile" "Release")
+endif()
+
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
+
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+        PROPERTIES
+        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+        )
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+#include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+    set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+  " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+        COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+        COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+        COMPONENT Runtime)
+
+install(FILES "${CMAKE_SOURCE_DIR}/../../scripts/linux/build/frostdart.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+        COMPONENT Runtime)
+
+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
+    install(FILES "${bundled_library}"
+            DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+            COMPONENT Runtime)
+endforeach(bundled_library)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+    install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+            COMPONENT Runtime)
+endif()
diff --git a/src/frostdart.c b/src/frostdart.c
deleted file mode 100644
index 7c39e12..0000000
--- a/src/frostdart.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "frostdart.h"
-
-// A very short-lived native function.
-//
-// For very short-lived functions, it is fine to call them on the main isolate.
-// They will block the Dart execution while running the native function, so
-// only do this for native functions which are guaranteed to be short-lived.
-FFI_PLUGIN_EXPORT intptr_t sum(intptr_t a, intptr_t b) { return a + b; }
-
-// A longer-lived native function, which occupies the thread calling it.
-//
-// Do not call these kind of native functions in the main isolate. They will
-// block Dart execution. This will cause dropped frames in Flutter applications.
-// Instead, call these native functions on a separate isolate.
-FFI_PLUGIN_EXPORT intptr_t sum_long_running(intptr_t a, intptr_t b) {
-  // Simulate work.
-#if _WIN32
-  Sleep(5000);
-#else
-  usleep(5000 * 1000);
-#endif
-  return a + b;
-}
diff --git a/src/frostdart.h b/src/frostdart.h
deleted file mode 100644
index 084c642..0000000
--- a/src/frostdart.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if _WIN32
-#include <windows.h>
-#else
-#include <pthread.h>
-#include <unistd.h>
-#endif
-
-#if _WIN32
-#define FFI_PLUGIN_EXPORT __declspec(dllexport)
-#else
-#define FFI_PLUGIN_EXPORT
-#endif
-
-// A very short-lived native function.
-//
-// For very short-lived functions, it is fine to call them on the main isolate.
-// They will block the Dart execution while running the native function, so
-// only do this for native functions which are guaranteed to be short-lived.
-FFI_PLUGIN_EXPORT intptr_t sum(intptr_t a, intptr_t b);
-
-// A longer lived native function, which occupies the thread calling it.
-//
-// Do not call these kind of native functions in the main isolate. They will
-// block Dart execution. This will cause dropped frames in Flutter applications.
-// Instead, call these native functions on a separate isolate.
-FFI_PLUGIN_EXPORT intptr_t sum_long_running(intptr_t a, intptr_t b);

From 203332efd0f049ef0e69d7590e8390bb037ff2a2 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 2 Aug 2023 11:40:14 -0600
Subject: [PATCH 06/49] "fix" example cmakelist

---
 example/linux/CMakeLists.txt | 72 +++++++++++++-----------------------
 1 file changed, 26 insertions(+), 46 deletions(-)

diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt
index f326f18..e5f7c36 100644
--- a/example/linux/CMakeLists.txt
+++ b/example/linux/CMakeLists.txt
@@ -1,19 +1,11 @@
-# Project-level configuration.
 cmake_minimum_required(VERSION 3.10)
 project(runner LANGUAGES CXX)
 
-# The name of the executable created for the application. Change this to change
-# the on-disk name of your application.
 set(BINARY_NAME "frostdart_example")
-# The unique GTK application identifier for this application. See:
-# https://wiki.gnome.org/HowDoI/ChooseApplicationID
 set(APPLICATION_ID "com.example.frostdart")
 
-# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
-# versions of CMake.
 cmake_policy(SET CMP0063 NEW)
 
-# Load bundled libraries from the lib/ directory relative to the binary.
 set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
 
 # Root filesystem for cross-building.
@@ -26,19 +18,15 @@ if(FLUTTER_TARGET_PLATFORM_SYSROOT)
   set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 endif()
 
-# Define build configuration options.
+# Configure build options.
 if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
   set(CMAKE_BUILD_TYPE "Debug" CACHE
-    STRING "Flutter build mode" FORCE)
+          STRING "Flutter build mode" FORCE)
   set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
-    "Debug" "Profile" "Release")
+          "Debug" "Profile" "Release")
 endif()
 
 # Compilation settings that should be applied to most targets.
-#
-# Be cautious about adding new options here, as plugins use this function by
-# default. In most cases, you should add new options to specific targets instead
-# of modifying this function.
 function(APPLY_STANDARD_SETTINGS TARGET)
   target_compile_features(${TARGET} PUBLIC cxx_std_14)
   target_compile_options(${TARGET} PRIVATE -Wall -Werror)
@@ -46,8 +34,9 @@ function(APPLY_STANDARD_SETTINGS TARGET)
   target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
 endfunction()
 
-# Flutter library and tool build rules.
 set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+
+# Flutter library and tool build rules.
 add_subdirectory(${FLUTTER_MANAGED_DIR})
 
 # System-level dependencies.
@@ -56,36 +45,24 @@ pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
 
 add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
 
-# Define the application target. To change its name, change BINARY_NAME above,
-# not the value here, or `flutter run` will no longer work.
-#
-# Any new source files that you add to the application should be added here.
+# Application build
 add_executable(${BINARY_NAME}
-  "main.cc"
-  "my_application.cc"
-  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
-)
-
-# Apply the standard set of build settings. This can be removed for applications
-# that need different build settings.
+        "main.cc"
+        "my_application.cc"
+        "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+        )
 apply_standard_settings(${BINARY_NAME})
-
-# Add dependency libraries. Add any application-specific dependencies here.
 target_link_libraries(${BINARY_NAME} PRIVATE flutter)
 target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
-
-# Run the Flutter tool portions of the build. This must not be removed.
 add_dependencies(${BINARY_NAME} flutter_assemble)
-
 # Only the install-generated bundle's copy of the executable will launch
 # correctly, since the resources must in the right relative locations. To avoid
 # people trying to run the unbundled copy, put it in a subdirectory instead of
 # the default top-level location.
 set_target_properties(${BINARY_NAME}
-  PROPERTIES
-  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
-)
-
+        PROPERTIES
+        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+        )
 
 # Generated plugin build rules, which manage building the plugins and adding
 # them to the application.
@@ -109,19 +86,22 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
 set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
 
 install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
-  COMPONENT Runtime)
+        COMPONENT Runtime)
 
 install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
-  COMPONENT Runtime)
+        COMPONENT Runtime)
 
 install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
-  COMPONENT Runtime)
+        COMPONENT Runtime)
 
-foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
-  install(FILES "${bundled_library}"
-    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
-    COMPONENT Runtime)
-endforeach(bundled_library)
+install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/linux/build/frostdart.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+        COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+  install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+          DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+          COMPONENT Runtime)
+endif()
 
 # Fully re-copy the assets directory on each build to avoid having stale files
 # from a previous install.
@@ -130,10 +110,10 @@ install(CODE "
   file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
   " COMPONENT Runtime)
 install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
-  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+        DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
 
 # Install the AOT library on non-Debug builds only.
 if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
   install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
-    COMPONENT Runtime)
+          COMPONENT Runtime)
 endif()

From 6d7db533e10a313ff47f95fe8438794ee9438b90 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 2 Aug 2023 12:45:07 -0600
Subject: [PATCH 07/49] fix types for quick example

---
 example/lib/main.dart | 12 ++++++------
 lib/frostdart.dart    | 19 +++++++++++--------
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/example/lib/main.dart b/example/lib/main.dart
index 7c18c59..9e03984 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -14,19 +14,19 @@ class MyApp extends StatefulWidget {
 }
 
 class _MyAppState extends State<MyApp> {
-  late CResult_MultisigConfigRes sumResult;
+  late CResult_MultisigConfigRes result;
 
-  String name = "REKT";
+  String name = "ERROR";
 
   @override
   void initState() {
     super.initState();
-    sumResult = frostdart.newMultisigConfig(
-        name: "Name AAAAAA",
+    result = frostdart.newMultisigConfig(
+        name: "Some kind of name",
         threshold: 3,
         participants: ["jimmy", "john", "toby"]);
 
-    // name = frostdart.multisigName(configRes: sumResult.value.ref);
+    name = frostdart.multisigName(configRes: result.value);
   }
 
   @override
@@ -51,7 +51,7 @@ class _MyAppState extends State<MyApp> {
                 ),
                 spacerSmall,
                 Text(
-                  'Type of result: ${sumResult.runtimeType}',
+                  'Type of result: ${result.runtimeType}',
                   style: textStyle,
                   textAlign: TextAlign.center,
                 ),
diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index cebefca..5e79dcf 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -30,12 +30,16 @@ CResult_MultisigConfigRes newMultisigConfig({
 }) {
   ffi.Pointer<ffi.Uint8> multisigName = name.toNativeUtf8().cast<ffi.Uint8>();
 
-  final joined = participants.join();
-  ffi.Pointer<ffi.Uint8> parts = joined.toNativeUtf8().cast<ffi.Uint8>();
+  ffi.Pointer<StringView> participantsPointer =
+      calloc<StringView>(participants.length);
 
-  ffi.Pointer<StringView> participantsPointer = calloc<StringView>();
-  participantsPointer.ref.ptr = parts;
-  participantsPointer.ref.len = joined.length;
+  for (int i = 0; i < participants.length; i++) {
+    final p = participants[i];
+    final svp = calloc<StringView>();
+    svp.ref.ptr = p.toNativeUtf8().cast<ffi.Uint8>();
+    svp.ref.len = p.length;
+    participantsPointer[i] = svp.ref;
+  }
 
   final result = _bindings.new_multisig_config(
     multisigName,
@@ -46,14 +50,13 @@ CResult_MultisigConfigRes newMultisigConfig({
   );
 
   calloc.free(multisigName);
-  calloc.free(parts);
   calloc.free(participantsPointer);
 
   return result;
 }
 
-String multisigName({required MultisigConfigRes configRes}) {
-  final result = _bindings.multisig_name(configRes.config);
+String multisigName({required ffi.Pointer<MultisigConfigRes> configRes}) {
+  final result = _bindings.multisig_name(configRes.ref.config);
 
   final bytes = result.ptr.asTypedList(result.len);
   final String name = String.fromCharCodes(bytes);

From 8e2183e743f14544bf4986cd4bf92d8f1282c7f6 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 2 Aug 2023 15:20:26 -0600
Subject: [PATCH 08/49] flight param refactor and added custom exception

---
 example/lib/main.dart |  6 +++--
 lib/frostdart.dart    | 15 ++++++++---
 lib/util.dart         | 63 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 6 deletions(-)
 create mode 100644 lib/util.dart

diff --git a/example/lib/main.dart b/example/lib/main.dart
index 9e03984..2c2b0a8 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,3 +1,5 @@
+import 'dart:ffi';
+
 import 'package:flutter/material.dart';
 import 'package:frostdart/frostdart.dart' as frostdart;
 import 'package:frostdart/frostdart_bindings_generated.dart';
@@ -14,7 +16,7 @@ class MyApp extends StatefulWidget {
 }
 
 class _MyAppState extends State<MyApp> {
-  late CResult_MultisigConfigRes result;
+  late Pointer<MultisigConfigRes> result;
 
   String name = "ERROR";
 
@@ -26,7 +28,7 @@ class _MyAppState extends State<MyApp> {
         threshold: 3,
         participants: ["jimmy", "john", "toby"]);
 
-    name = frostdart.multisigName(configRes: result.value);
+    name = frostdart.multisigName(multisigConfigPointer: result.ref.config);
   }
 
   @override
diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 5e79dcf..524428e 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -3,6 +3,7 @@ import 'dart:io';
 
 import 'package:ffi/ffi.dart';
 import 'package:frostdart/frostdart_bindings_generated.dart';
+import 'package:frostdart/util.dart';
 
 const String _libName = 'frostdart';
 
@@ -23,7 +24,7 @@ final ffi.DynamicLibrary _dylib = () {
 /// The bindings to the native functions in [_dylib].
 final FrostdartBindings _bindings = FrostdartBindings(_dylib);
 
-CResult_MultisigConfigRes newMultisigConfig({
+ffi.Pointer<MultisigConfigRes> newMultisigConfig({
   required String name,
   required int threshold,
   required List<String> participants,
@@ -52,11 +53,17 @@ CResult_MultisigConfigRes newMultisigConfig({
   calloc.free(multisigName);
   calloc.free(participantsPointer);
 
-  return result;
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
 }
 
-String multisigName({required ffi.Pointer<MultisigConfigRes> configRes}) {
-  final result = _bindings.multisig_name(configRes.ref.config);
+String multisigName({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+}) {
+  final result = _bindings.multisig_name(multisigConfigPointer);
 
   final bytes = result.ptr.asTypedList(result.len);
   final String name = String.fromCharCodes(bytes);
diff --git a/lib/util.dart b/lib/util.dart
new file mode 100644
index 0000000..50e0f7a
--- /dev/null
+++ b/lib/util.dart
@@ -0,0 +1,63 @@
+class FrostdartException implements Exception {
+  final int errorCode;
+
+  FrostdartException({required this.errorCode});
+
+  @override
+  String toString() {
+    return "FrostdartException: ${getErrorName(errorCode)}";
+  }
+}
+
+const int SUCCESS = 0;
+
+String getErrorName(int errorCode) {
+  switch (errorCode) {
+    case 101:
+      return 'UNKNOWN_ERROR';
+    case 102:
+      return 'INVALID_ENCODING_ERROR';
+    case 103:
+      return 'INVALID_PARTICIPANT_ERROR';
+    case 104:
+      return 'INVALID_SHARE_ERROR';
+    case 201:
+      return 'ZERO_PARAMETER_ERROR';
+    case 202:
+      return 'INVALID_THRESHOLD_ERROR';
+    case 203:
+      return 'INVALID_NAME_ERROR';
+    case 204:
+      return 'UNKNOWN_LANGUAGE_ERROR';
+    case 205:
+      return 'INVALID_SEED_ERROR';
+    case 206:
+      return 'INVALID_AMOUNT_OF_COMMITMENTS_ERROR';
+    case 207:
+      return 'INVALID_COMMITMENTS_ERROR';
+    case 208:
+      return 'INVALID_AMOUNT_OF_SHARES_ERROR';
+    case 301:
+      return 'INVALID_OUTPUT_ERROR';
+    case 302:
+      return 'INVALID_ADDRESS_ERROR';
+    case 303:
+      return 'INVALID_NETWORK_ERROR';
+    case 304:
+      return 'NO_INPUTS_ERROR';
+    case 305:
+      return 'NO_OUTPUTS_ERROR';
+    case 306:
+      return 'DUST_ERROR';
+    case 307:
+      return 'NOT_ENOUGH_FUNDS_ERROR';
+    case 308:
+      return 'TOO_LARGE_TRANSACTION_ERROR';
+    case 309:
+      return 'WRONG_KEYS_ERROR';
+    case 310:
+      return 'INVALID_PREPROCESS_ERROR';
+    default:
+      return 'UNKNOWN ERROR CODE "$errorCode"';
+  }
+}

From 374f7d645c00cd7580bbef173bdafcdc371828bc Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 2 Aug 2023 17:42:12 -0600
Subject: [PATCH 09/49] wrap all bound functions, converting non opaque types
 to dart native types

---
 lib/frostdart.dart | 523 +++++++++++++++++++++++++++++++++++++++++++--
 lib/output.dart    |  15 ++
 lib/util.dart      |  20 ++
 3 files changed, 545 insertions(+), 13 deletions(-)
 create mode 100644 lib/output.dart

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 524428e..ffa983b 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -1,8 +1,10 @@
 import 'dart:ffi' as ffi;
 import 'dart:io';
+import 'dart:typed_data';
 
 import 'package:ffi/ffi.dart';
 import 'package:frostdart/frostdart_bindings_generated.dart';
+import 'package:frostdart/output.dart';
 import 'package:frostdart/util.dart';
 
 const String _libName = 'frostdart';
@@ -24,6 +26,86 @@ final ffi.DynamicLibrary _dylib = () {
 /// The bindings to the native functions in [_dylib].
 final FrostdartBindings _bindings = FrostdartBindings(_dylib);
 
+// =============================================================================
+// ===== wrapped functions to make them as close to pure dart as possible ======
+//TODO: check missing frees
+
+void freeOwnedString(OwnedString ownedString) {
+  return _bindings.free_owned_string(ownedString);
+}
+
+String multisigName({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+}) {
+  final result = _bindings.multisig_name(multisigConfigPointer);
+
+  final bytes = result.ptr.asTypedList(result.len);
+  final String name = String.fromCharCodes(bytes);
+
+  return name;
+}
+
+int multisigThreshold({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+}) {
+  return _bindings.multisig_threshold(multisigConfigPointer);
+}
+
+int multisigParticipants({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+}) {
+  return _bindings.multisig_participants(multisigConfigPointer);
+}
+
+String multisigParticipant({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+  required int index,
+}) {
+  final stringView = _bindings.multisig_participant(
+    multisigConfigPointer,
+    index,
+  );
+
+  final utf8Pointer = stringView.ptr.cast<Utf8>();
+  final string = utf8Pointer.toDartString(length: stringView.len);
+
+  calloc.free(utf8Pointer);
+
+  return string;
+}
+
+Uint8List multisigSalt({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+}) {
+  final uint8Pointer = _bindings.multisig_salt(multisigConfigPointer);
+  final bytes = uint8Pointer.asTypedList(SALT_BYTES_LENGTH);
+
+  calloc.free(uint8Pointer);
+
+  return bytes;
+}
+
+ffi.Pointer<MultisigConfig> multisigConfig({
+  required ffi.Pointer<MultisigConfigWithName> multisigConfigWithNamePointer,
+}) {
+  return _bindings.multisig_config(multisigConfigWithNamePointer);
+}
+
+String multisigMyName({
+  required ffi.Pointer<MultisigConfigWithName> multisigConfigWithNamePointer,
+}) {
+  final stringView = _bindings.multisig_my_name(
+    multisigConfigWithNamePointer,
+  );
+
+  final utf8Pointer = stringView.ptr.cast<Utf8>();
+  final string = utf8Pointer.toDartString(length: stringView.len);
+
+  calloc.free(utf8Pointer);
+
+  return string;
+}
+
 ffi.Pointer<MultisigConfigRes> newMultisigConfig({
   required String name,
   required int threshold,
@@ -31,15 +113,22 @@ ffi.Pointer<MultisigConfigRes> newMultisigConfig({
 }) {
   ffi.Pointer<ffi.Uint8> multisigName = name.toNativeUtf8().cast<ffi.Uint8>();
 
-  ffi.Pointer<StringView> participantsPointer =
-      calloc<StringView>(participants.length);
+  ffi.Pointer<StringView> participantsPointer = calloc<StringView>(
+    participants.length,
+  );
 
   for (int i = 0; i < participants.length; i++) {
-    final p = participants[i];
-    final svp = calloc<StringView>();
-    svp.ref.ptr = p.toNativeUtf8().cast<ffi.Uint8>();
-    svp.ref.len = p.length;
-    participantsPointer[i] = svp.ref;
+    // TODO: is this needed?
+    // final participant = participants[i];
+    // final stringViewPointer = calloc<StringView>();
+    // stringViewPointer.ref.ptr = participant.toNativeUtf8().cast<ffi.Uint8>();
+    // stringViewPointer.ref.len = participant.length;
+    // participantsPointer[i] = stringViewPointer.ref;
+
+    // TODO: or does this suffice?
+    participantsPointer[i].len = participants[i].length;
+    participantsPointer[i].ptr =
+        participants[i].toNativeUtf8().cast<ffi.Uint8>();
   }
 
   final result = _bindings.new_multisig_config(
@@ -60,13 +149,421 @@ ffi.Pointer<MultisigConfigRes> newMultisigConfig({
   }
 }
 
-String multisigName({
-  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+ffi.Pointer<MultisigConfig> decodeMultisigConfig({
+  required String multisigConfig,
 }) {
-  final result = _bindings.multisig_name(multisigConfigPointer);
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = multisigConfig.toNativeUtf8().cast<ffi.Uint8>();
+  stringViewPointer.ref.len = multisigConfig.length;
 
-  final bytes = result.ptr.asTypedList(result.len);
-  final String name = String.fromCharCodes(bytes);
+  final result = _bindings.decode_multisig_config(stringViewPointer.ref);
 
-  return name;
+  calloc.free(stringViewPointer.ref.ptr);
+  calloc.free(stringViewPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+ffi.Pointer<StartKeyGenRes> startKeyGen({
+  required ffi.Pointer<MultisigConfig> multisigConfig,
+  required String myName,
+  required Language language,
+}) {
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = myName.toNativeUtf8().cast<ffi.Uint8>();
+  stringViewPointer.ref.len = myName.length;
+
+  final result = _bindings.start_key_gen(
+    multisigConfig,
+    stringViewPointer.ref,
+    language.code,
+  );
+
+  calloc.free(stringViewPointer.ref.ptr);
+  calloc.free(stringViewPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+ffi.Pointer<SecretSharesRes> getSecretShares({
+  required ffi.Pointer<MultisigConfigWithName> multisigConfigWithName,
+  required String seed,
+  required Language language,
+  required ffi.Pointer<SecretShareMachineWrapper> machine,
+  required List<String> commitments,
+}) {
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = seed.toNativeUtf8().cast<ffi.Uint8>();
+  stringViewPointer.ref.len = seed.length;
+
+  ffi.Pointer<StringView> commitmentsPointer =
+      calloc<StringView>(commitments.length);
+
+  for (int i = 0; i < commitments.length; i++) {
+    final commitment = commitments[i];
+    final stringViewPointer = calloc<StringView>();
+    stringViewPointer.ref.ptr = commitment.toNativeUtf8().cast<ffi.Uint8>();
+    stringViewPointer.ref.len = commitment.length;
+    commitmentsPointer[i] = stringViewPointer.ref;
+  }
+
+  final result = _bindings.get_secret_shares(
+    multisigConfigWithName,
+    language.code,
+    stringViewPointer.ref,
+    machine,
+    commitmentsPointer,
+    commitments.length,
+  );
+
+  calloc.free(stringViewPointer.ref.ptr);
+  calloc.free(stringViewPointer);
+  calloc.free(commitmentsPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+ffi.Pointer<KeyGenRes> completeKeyGen({
+  required ffi.Pointer<MultisigConfigWithName> multisigConfigWithName,
+  required ffi.Pointer<SecretSharesRes> machineAndCommitments,
+  required List<String> shares,
+}) {
+  ffi.Pointer<StringView> sharesPointer = calloc<StringView>(shares.length);
+
+  for (int i = 0; i < shares.length; i++) {
+    final share = shares[i];
+    final stringViewPointer = calloc<StringView>();
+    stringViewPointer.ref.ptr = share.toNativeUtf8().cast<ffi.Uint8>();
+    stringViewPointer.ref.len = share.length;
+    sharesPointer[i] = stringViewPointer.ref;
+  }
+
+  final result = _bindings.complete_key_gen(
+    multisigConfigWithName,
+    machineAndCommitments.ref,
+    sharesPointer,
+    shares.length,
+  );
+
+  calloc.free(sharesPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+String serializeKeys({
+  required ffi.Pointer<ThresholdKeysWrapper> keys,
+}) {
+  final ownedString = _bindings.serialize_keys(keys);
+
+  final string = ownedString.ptr.cast<Utf8>().toDartString(
+        length: ownedString.len,
+      );
+
+  _bindings.free_owned_string(ownedString);
+
+  return string;
+}
+
+ffi.Pointer<ThresholdKeysWrapper> deserializeKeys({
+  required String keys,
+}) {
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = keys.toNativeUtf8().cast<ffi.Uint8>();
+  stringViewPointer.ref.len = keys.length;
+
+  final result = _bindings.deserialize_keys(stringViewPointer.ref);
+
+  calloc.free(stringViewPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+Output convertOutput({
+  required ffi.Pointer<OwnedPortableOutput> ownedPortableOutputPointer,
+}) {
+  final hashPointer = _bindings.output_hash(ownedPortableOutputPointer);
+  final hash = hashPointer.asTypedList(HASH_BYTES_LENGTH);
+  calloc.free(hashPointer);
+
+  final vout = _bindings.output_vout(ownedPortableOutputPointer);
+
+  final value = _bindings.output_value(ownedPortableOutputPointer);
+
+  final scriptPubKeyLength =
+      _bindings.output_script_pubkey_len(ownedPortableOutputPointer);
+
+  final scriptPubKeyPointer = _bindings.output_hash(ownedPortableOutputPointer);
+  final scriptPubKey = scriptPubKeyPointer.asTypedList(scriptPubKeyLength);
+  calloc.free(scriptPubKeyPointer);
+
+  return Output(
+    hash: hash,
+    vout: vout,
+    value: value,
+    scriptPubKey: scriptPubKey,
+  );
+}
+
+int signInputs({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+}) {
+  return _bindings.sign_inputs(signConfigPointer);
+}
+
+ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> signInput({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+  required int index,
+}) {
+  return _bindings.sign_input(signConfigPointer, index);
+}
+
+int signPayments({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+}) {
+  return _bindings.sign_payments(signConfigPointer);
+}
+
+String signPaymentAddress({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+  required int index,
+}) {
+  final stringView = _bindings.sign_payment_address(
+    signConfigPointer,
+    index,
+  );
+
+  final utf8Pointer = stringView.ptr.cast<Utf8>();
+  final string = utf8Pointer.toDartString(length: stringView.len);
+
+  calloc.free(utf8Pointer);
+
+  return string;
+}
+
+int signPaymentAmount({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+  required int index,
+}) {
+  return _bindings.sign_payment_amount(signConfigPointer, index);
+}
+
+String signChange({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+}) {
+  final stringView = _bindings.sign_change(
+    signConfigPointer,
+  );
+
+  final utf8Pointer = stringView.ptr.cast<Utf8>();
+  final string = utf8Pointer.toDartString(length: stringView.len);
+
+  calloc.free(utf8Pointer);
+
+  return string;
+}
+
+int signFeePerWeight({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+  required int index,
+}) {
+  return _bindings.sign_fee_per_weight(signConfigPointer);
+}
+
+ffi.Pointer<SignConfigRes> newSignConfig({
+  required int network,
+  required List<Output> outputs,
+  required int payments,
+  required List<String> paymentAddresses,
+  required List<int> paymentAmounts,
+  required String change,
+  required int feePerWeight,
+}) {
+  final outputsPointer = calloc<PortableOutput>(outputs.length);
+  for (int i = 0; i < outputs.length; i++) {
+    outputsPointer[i].vout = outputs[i].vout;
+    outputsPointer[i].value = outputs[i].value;
+
+    final hashLength = outputs[i].hash.length;
+    final hashArr = ffi.Array<ffi.Uint8>(hashLength);
+    for (int j = 0; j < hashLength; j++) {
+      hashArr[j] = outputs[i].hash[j];
+    }
+    outputsPointer[i].hash = hashArr;
+    outputsPointer[i].script_pubkey_len = outputs[i].scriptPubKey.length;
+
+    outputsPointer[i].script_pubkey =
+        calloc<ffi.Uint8>(outputsPointer[i].script_pubkey_len);
+    for (int j = 0; j < outputsPointer[i].script_pubkey_len; j++) {
+      outputsPointer[i].script_pubkey.elementAt(j).value = outputs[i].hash[j];
+    }
+  }
+
+  final paymentAddressesPointer = calloc<StringView>(
+    paymentAddresses.length,
+  );
+  for (int i = 0; i < paymentAddresses.length; i++) {
+    paymentAddressesPointer[i].len = paymentAddresses[i].length;
+    paymentAddressesPointer[i].ptr =
+        paymentAddresses[i].toNativeUtf8().cast<ffi.Uint8>();
+  }
+
+  final paymentAmountsPointer = calloc<ffi.Uint64>(paymentAmounts.length);
+  for (int i = 0; i < paymentAmounts.length; i++) {
+    paymentAmountsPointer[i] = paymentAmounts[i];
+  }
+
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = change
+      .toNativeUtf8(
+        allocator: calloc,
+      )
+      .cast<ffi.Uint8>();
+  stringViewPointer.ref.len = change.length;
+
+  final result = _bindings.new_sign_config(
+    network,
+    outputsPointer,
+    outputs.length,
+    payments,
+    paymentAddressesPointer,
+    paymentAmountsPointer,
+    stringViewPointer.ref,
+    feePerWeight,
+  );
+
+  // TODO: frees
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+ffi.Pointer<SignConfig> decodeSignConfig({
+  required int network,
+  required String encodedSignConfig,
+}) {
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = encodedSignConfig
+      .toNativeUtf8(
+        allocator: calloc,
+      )
+      .cast<ffi.Uint8>();
+  stringViewPointer.ref.len = encodedSignConfig.length;
+
+  final result = _bindings.decode_sign_config(
+    network,
+    stringViewPointer.ref,
+  );
+
+  calloc.free(stringViewPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+ffi.Pointer<AttemptSignRes> attemptSign({
+  required ffi.Pointer<ThresholdKeysWrapper> thresholdKeysWrapperPointer,
+  required ffi.Pointer<ffi.Pointer<SignConfig>> signConfigPointer,
+}) {
+  final result = _bindings.attempt_sign(
+    thresholdKeysWrapperPointer,
+    signConfigPointer,
+  );
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+ffi.Pointer<ContinueSignRes> continueSign({
+  required ffi.Pointer<TransactionSignMachineWrapper> machine,
+  required List<String> preprocesses,
+}) {
+  final preprocessesPointer = calloc<StringView>(preprocesses.length);
+  for (int i = 0; i < preprocesses.length; i++) {
+    preprocessesPointer[i].len = preprocesses[i].length;
+    preprocessesPointer[i].ptr = preprocesses[i]
+        .toNativeUtf8(
+          allocator: calloc,
+        )
+        .cast<ffi.Uint8>();
+  }
+
+  final result = _bindings.continue_sign(
+    machine,
+    preprocessesPointer,
+    preprocesses.length,
+  );
+
+  calloc.free(preprocessesPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result.value;
+  }
+}
+
+String completeSign({
+  required ffi.Pointer<TransactionSignatureMachineWrapper> machine,
+  required List<String> shares,
+}) {
+  final sharesPointer = calloc<StringView>(shares.length);
+  for (int i = 0; i < shares.length; i++) {
+    sharesPointer[i].len = shares[i].length;
+    sharesPointer[i].ptr = shares[i]
+        .toNativeUtf8(
+          allocator: calloc,
+        )
+        .cast<ffi.Uint8>();
+  }
+
+  final result = _bindings.complete_sign(
+    machine,
+    sharesPointer,
+    shares.length,
+  );
+
+  calloc.free(sharesPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    final ownedString = result.value.ref;
+
+    final string = ownedString.ptr.cast<Utf8>().toDartString(
+          length: ownedString.len,
+        );
+
+    _bindings.free_owned_string(ownedString);
+
+    return string;
+  }
 }
diff --git a/lib/output.dart b/lib/output.dart
new file mode 100644
index 0000000..fc1cb51
--- /dev/null
+++ b/lib/output.dart
@@ -0,0 +1,15 @@
+import 'dart:typed_data';
+
+class Output {
+  final Uint8List hash;
+  final int vout;
+  final int value;
+  final Uint8List scriptPubKey;
+
+  Output({
+    required this.hash,
+    required this.vout,
+    required this.value,
+    required this.scriptPubKey,
+  });
+}
diff --git a/lib/util.dart b/lib/util.dart
index 50e0f7a..c6eef1b 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -1,3 +1,5 @@
+import 'package:frostdart/frostdart_bindings_generated.dart';
+
 class FrostdartException implements Exception {
   final int errorCode;
 
@@ -9,8 +11,26 @@ class FrostdartException implements Exception {
   }
 }
 
+const int SALT_BYTES_LENGTH = 32;
+const int HASH_BYTES_LENGTH = 32;
 const int SUCCESS = 0;
 
+enum Language {
+  english(LANGUAGE_ENGLISH),
+  chineseSimplified(LANGUAGE_CHINESE_SIMPLIFIED),
+  chineseTraditional(LANGUAGE_CHINESE_TRADITIONAL),
+  french(LANGUAGE_FRENCH),
+  italian(LANGUAGE_ITALIAN),
+  japanese(LANGUAGE_JAPANESE),
+  korean(LANGUAGE_KOREAN),
+  spanish(LANGUAGE_SPANISH),
+  ;
+
+  final int code;
+
+  const Language(this.code);
+}
+
 String getErrorName(int errorCode) {
   switch (errorCode) {
     case 101:

From d41e35449ef1c1c858f653e3fcb94f7b75f023ce Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 3 Aug 2023 09:59:07 -0600
Subject: [PATCH 10/49] example run ui

---
 example/lib/frost_sample_run.dart |  15 ++++
 example/lib/main.dart             | 109 ++++++++++++++++++------------
 2 files changed, 81 insertions(+), 43 deletions(-)
 create mode 100644 example/lib/frost_sample_run.dart

diff --git a/example/lib/frost_sample_run.dart b/example/lib/frost_sample_run.dart
new file mode 100644
index 0000000..652880b
--- /dev/null
+++ b/example/lib/frost_sample_run.dart
@@ -0,0 +1,15 @@
+import 'package:flutter/foundation.dart';
+
+abstract class FrostSampleRunner {
+  static String _run(int dummy) {
+    // do things
+
+    // return "success" or return early with error message string
+    return "success";
+  }
+
+  static Future<String> run() async {
+    await Future.delayed(const Duration(seconds: 2));
+    return await compute(_run, 1);
+  }
+}
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 2c2b0a8..97a0cbc 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,8 +1,5 @@
-import 'dart:ffi';
-
 import 'package:flutter/material.dart';
-import 'package:frostdart/frostdart.dart' as frostdart;
-import 'package:frostdart/frostdart_bindings_generated.dart';
+import 'package:frostdart_example/frost_sample_run.dart';
 
 void main() {
   runApp(const MyApp());
@@ -16,57 +13,83 @@ class MyApp extends StatefulWidget {
 }
 
 class _MyAppState extends State<MyApp> {
-  late Pointer<MultisigConfigRes> result;
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      home: Scaffold(
+        appBar: AppBar(
+          title: const Text('frostdart'),
+        ),
+        body: const Column(
+          crossAxisAlignment: CrossAxisAlignment.stretch,
+          children: [
+            Expanded(
+              child: Content(),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
 
-  String name = "ERROR";
+class Content extends StatefulWidget {
+  const Content({super.key});
+
+  @override
+  State<Content> createState() => _ContentState();
+}
+
+class _ContentState extends State<Content> {
+  String? result;
+
+  late bool enableButton;
 
   @override
   void initState() {
+    enableButton = true;
     super.initState();
-    result = frostdart.newMultisigConfig(
-        name: "Some kind of name",
-        threshold: 3,
-        participants: ["jimmy", "john", "toby"]);
-
-    name = frostdart.multisigName(multisigConfigPointer: result.ref.config);
   }
 
   @override
   Widget build(BuildContext context) {
     const textStyle = TextStyle(fontSize: 25);
     const spacerSmall = SizedBox(height: 10);
-    return MaterialApp(
-      home: Scaffold(
-        appBar: AppBar(
-          title: const Text('Native Packages'),
-        ),
-        body: SingleChildScrollView(
-          child: Container(
-            padding: const EdgeInsets.all(10),
-            child: Column(
-              children: [
-                const Text(
-                  'This calls a native function through FFI that is shipped as source in the package. '
-                  'The native code is built as part of the Flutter Runner build.',
-                  style: textStyle,
-                  textAlign: TextAlign.center,
-                ),
-                spacerSmall,
-                Text(
-                  'Type of result: ${result.runtimeType}',
-                  style: textStyle,
-                  textAlign: TextAlign.center,
-                ),
-                spacerSmall,
-                Text(
-                  'name: $name',
-                  style: textStyle,
-                  textAlign: TextAlign.center,
-                ),
-              ],
-            ),
+    return Container(
+      padding: const EdgeInsets.all(10),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.center,
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          TextButton(
+            onPressed: () async {
+              setState(() {
+                enableButton = false;
+              });
+              showDialog(
+                  barrierDismissible: false,
+                  context: context,
+                  builder: (context) =>
+                      const AlertDialog(title: Text("Running")));
+              result = await FrostSampleRunner.run();
+              if (mounted) {
+                Navigator.of(context).pop();
+                setState(() {
+                  enableButton = true;
+                });
+              }
+            },
+            child: const Text("RUN"),
           ),
-        ),
+          spacerSmall,
+          spacerSmall,
+          spacerSmall,
+          Text(
+            'Result: ${result.toString()}',
+            style: textStyle,
+            textAlign: TextAlign.center,
+          ),
+        ],
       ),
     );
   }

From 4f05a15b27e73d35ff431f5cd5e8fde9b2922396 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 3 Aug 2023 10:01:14 -0600
Subject: [PATCH 11/49] OwnedString toDartString extension

---
 lib/frostdart.dart |  8 ++------
 lib/util.dart      | 10 ++++++++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index ffa983b..02fa6fd 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -271,9 +271,7 @@ String serializeKeys({
 }) {
   final ownedString = _bindings.serialize_keys(keys);
 
-  final string = ownedString.ptr.cast<Utf8>().toDartString(
-        length: ownedString.len,
-      );
+  final string = ownedString.toDartString();
 
   _bindings.free_owned_string(ownedString);
 
@@ -558,9 +556,7 @@ String completeSign({
   } else {
     final ownedString = result.value.ref;
 
-    final string = ownedString.ptr.cast<Utf8>().toDartString(
-          length: ownedString.len,
-        );
+    final string = ownedString.toDartString();
 
     _bindings.free_owned_string(ownedString);
 
diff --git a/lib/util.dart b/lib/util.dart
index c6eef1b..cdcf359 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -1,3 +1,4 @@
+import 'package:ffi/ffi.dart';
 import 'package:frostdart/frostdart_bindings_generated.dart';
 
 class FrostdartException implements Exception {
@@ -81,3 +82,12 @@ String getErrorName(int errorCode) {
       return 'UNKNOWN ERROR CODE "$errorCode"';
   }
 }
+
+extension OwnedStringExt on OwnedString {
+  String toDartString() {
+    final string = ptr.cast<Utf8>().toDartString(
+          length: len,
+        );
+    return string;
+  }
+}

From f23682106535c16ddfbeb5f867663428c4ce8802 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 3 Aug 2023 11:06:52 -0600
Subject: [PATCH 12/49] WIP sample testing run

---
 example/lib/frost_sample_run.dart | 81 ++++++++++++++++++++++++++++---
 1 file changed, 75 insertions(+), 6 deletions(-)

diff --git a/example/lib/frost_sample_run.dart b/example/lib/frost_sample_run.dart
index 652880b..a059abb 100644
--- a/example/lib/frost_sample_run.dart
+++ b/example/lib/frost_sample_run.dart
@@ -1,15 +1,84 @@
+import 'dart:ffi';
+
 import 'package:flutter/foundation.dart';
+import 'package:frostdart/frostdart.dart';
+import 'package:frostdart/util.dart';
 
 abstract class FrostSampleRunner {
-  static String _run(int dummy) {
-    // do things
+  static String _run(int? dummy) {
+    try {
+      // do things
+
+      final config = newMultisigConfig(
+        name: "alice",
+        threshold: 1,
+        participants: [
+          "alice",
+          "bob",
+        ],
+      );
+
+      final encodedConfig = config.ref.encoded.toDartString();
+
+      final startGenAlice = startKeyGen(
+        multisigConfig: decodeMultisigConfig(multisigConfig: encodedConfig),
+        myName: "alice",
+        language: Language.english,
+      );
+
+      final startGenBob = startKeyGen(
+        multisigConfig: decodeMultisigConfig(multisigConfig: encodedConfig),
+        myName: "bob",
+        language: Language.english,
+      );
+
+      final seedAlice = startGenAlice.ref.seed.toDartString();
+      final seedBob = startGenBob.ref.seed.toDartString();
+      debugPrint("seedAlice: $seedAlice");
+      debugPrint("seedBob: $seedBob");
+
+      final commitments = [
+        startGenAlice.ref.commitments.toDartString(),
+        startGenBob.ref.commitments.toDartString(),
+      ];
+      debugPrint("commitments: $commitments");
+
+      final secretSharesAlice = getSecretShares(
+        multisigConfigWithName: startGenAlice.ref.config,
+        seed: seedAlice,
+        language: Language.english,
+        machine: startGenAlice.ref.machine,
+        commitments: commitments,
+      );
+      final secretSharesBob = getSecretShares(
+        multisigConfigWithName: startGenBob.ref.config,
+        seed: seedBob,
+        language: Language.english,
+        machine: startGenBob.ref.machine,
+        commitments: commitments,
+      );
+
+      final List<String> shares = [
+        secretSharesAlice.ref.shares.toDartString(),
+        secretSharesBob.ref.shares.toDartString(),
+      ];
+      debugPrint("shares: $shares");
+
+      final completeGen = completeKeyGen(
+        multisigConfigWithName: startGenAlice.ref.config,
+        machineAndCommitments: secretSharesAlice,
+        shares: shares,
+      );
 
-    // return "success" or return early with error message string
-    return "success";
+      // return "success" or return early with error message string
+      return "success";
+    } catch (e, s) {
+      debugPrint("run error: $e\n$s");
+      return e.toString();
+    }
   }
 
   static Future<String> run() async {
-    await Future.delayed(const Duration(seconds: 2));
-    return await compute(_run, 1);
+    return await compute(_run, null);
   }
 }

From 2e801aa3f31de2b43cdaa988f739ba2c1231d3f8 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 3 Aug 2023 11:57:06 -0600
Subject: [PATCH 13/49] update ref

---
 src/serai | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serai b/src/serai
index 1674b21..a9a9260 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 1674b21712a87297bf30c291163a21e6158212f7
+Subproject commit a9a9260eabdbc7eb20ddf54f8e413e64e747f024

From 9e78f56a33e9448189d4e345cc01e492b5734fc1 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 3 Aug 2023 11:57:41 -0600
Subject: [PATCH 14/49] full rebuild in build script

---
 scripts/linux/build_all.sh | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh
index 14d31c0..b86eeb5 100755
--- a/scripts/linux/build_all.sh
+++ b/scripts/linux/build_all.sh
@@ -4,6 +4,8 @@ ROOT_DIR="$(pwd)/../.."
 
 mkdir -p build
 
+rm -rf "$ROOT_DIR"/src/serai/target
+
 cd "$ROOT_DIR"/src/serai/hrf || exit
 if [ "$IS_ARM" = true ]  ; then
     echo "Building arm frostdart"

From ad2a070ab1469e74ecdfa849fb366f295dd1996e Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 3 Aug 2023 13:53:20 -0600
Subject: [PATCH 15/49] update ref

---
 src/serai | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serai b/src/serai
index a9a9260..001d60c 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit a9a9260eabdbc7eb20ddf54f8e413e64e747f024
+Subproject commit 001d60cb46169061d87ec2115fa96cb1d45a5043

From 9e18598b261f4e028b80e7c2e48ea7e580270cfd Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 07:55:24 -0600
Subject: [PATCH 16/49] update ref and affected bindings

---
 lib/frostdart.dart                    | 2 +-
 lib/frostdart_bindings_generated.dart | 8 ++++----
 src/serai                             | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 02fa6fd..ed4257c 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -486,7 +486,7 @@ ffi.Pointer<SignConfig> decodeSignConfig({
 
 ffi.Pointer<AttemptSignRes> attemptSign({
   required ffi.Pointer<ThresholdKeysWrapper> thresholdKeysWrapperPointer,
-  required ffi.Pointer<ffi.Pointer<SignConfig>> signConfigPointer,
+  required ffi.Pointer<SignConfig> signConfigPointer,
 }) {
   final result = _bindings.attempt_sign(
     thresholdKeysWrapperPointer,
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index e8e5d4b..1333e40 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -539,7 +539,7 @@ class FrostdartBindings {
 
   CResult_AttemptSignRes attempt_sign(
     ffi.Pointer<ThresholdKeysWrapper> keys,
-    ffi.Pointer<ffi.Pointer<SignConfig>> config,
+    ffi.Pointer<SignConfig> config,
   ) {
     return _attempt_sign(
       keys,
@@ -550,10 +550,10 @@ class FrostdartBindings {
   late final _attempt_signPtr = _lookup<
       ffi.NativeFunction<
           CResult_AttemptSignRes Function(ffi.Pointer<ThresholdKeysWrapper>,
-              ffi.Pointer<ffi.Pointer<SignConfig>>)>>('attempt_sign');
+              ffi.Pointer<SignConfig>)>>('attempt_sign');
   late final _attempt_sign = _attempt_signPtr.asFunction<
-      CResult_AttemptSignRes Function(ffi.Pointer<ThresholdKeysWrapper>,
-          ffi.Pointer<ffi.Pointer<SignConfig>>)>();
+      CResult_AttemptSignRes Function(
+          ffi.Pointer<ThresholdKeysWrapper>, ffi.Pointer<SignConfig>)>();
 
   CResult_ContinueSignRes continue_sign(
     ffi.Pointer<TransactionSignMachineWrapper> machine,
diff --git a/src/serai b/src/serai
index 001d60c..0298704 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 001d60cb46169061d87ec2115fa96cb1d45a5043
+Subproject commit 02987043d2c097ffcc3bea8c1dce67086707d1bc

From 2fd5ec3f265f1e7cda7881cf25b3e244b264264e Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 08:17:34 -0600
Subject: [PATCH 17/49] basic working keygen example

---
 example/lib/frost_sample_run.dart | 54 +++++++++++++++++++++++++------
 example/lib/main.dart             | 25 ++++++++------
 lib/util.dart                     |  1 +
 3 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/example/lib/frost_sample_run.dart b/example/lib/frost_sample_run.dart
index a059abb..f346384 100644
--- a/example/lib/frost_sample_run.dart
+++ b/example/lib/frost_sample_run.dart
@@ -5,11 +5,13 @@ import 'package:frostdart/frostdart.dart';
 import 'package:frostdart/util.dart';
 
 abstract class FrostSampleRunner {
-  static String _run(int? dummy) {
-    try {
-      // do things
+  static Future<String> runKeygen() async {
+    return await compute(_runKeygen, null);
+  }
 
-      final config = newMultisigConfig(
+  static String _runKeygen(int? dummy) {
+    try {
+      final sharedMultisigConfig = newMultisigConfig(
         name: "alice",
         threshold: 1,
         participants: [
@@ -18,7 +20,7 @@ abstract class FrostSampleRunner {
         ],
       );
 
-      final encodedConfig = config.ref.encoded.toDartString();
+      final encodedConfig = sharedMultisigConfig.ref.encoded.toDartString();
 
       final startGenAlice = startKeyGen(
         multisigConfig: decodeMultisigConfig(multisigConfig: encodedConfig),
@@ -64,12 +66,48 @@ abstract class FrostSampleRunner {
       ];
       debugPrint("shares: $shares");
 
-      final completeGen = completeKeyGen(
+      final completeGenAlice = completeKeyGen(
         multisigConfigWithName: startGenAlice.ref.config,
         machineAndCommitments: secretSharesAlice,
         shares: shares,
       );
 
+      final completeGenBob = completeKeyGen(
+        multisigConfigWithName: startGenBob.ref.config,
+        machineAndCommitments: secretSharesBob,
+        shares: shares,
+      );
+
+      final idAlice = Uint8List.fromList(
+        List<int>.generate(
+          MULTISIG_ID_LENGTH,
+          (index) => completeGenAlice.ref.multisig_id[index],
+        ),
+      );
+      final idBob = Uint8List.fromList(
+        List<int>.generate(
+          MULTISIG_ID_LENGTH,
+          (index) => completeGenBob.ref.multisig_id[index],
+        ),
+      );
+      debugPrint("ID Alice: $idAlice");
+      debugPrint("ID Bob: $idBob");
+
+      final recoveryAlice = completeGenAlice.ref.recovery.toDartString();
+      final recoveryBob = completeGenBob.ref.recovery.toDartString();
+      debugPrint("recoveryAlice: $recoveryAlice");
+      debugPrint("recoveryBob: $recoveryBob");
+
+      for (int i = 0; i < MULTISIG_ID_LENGTH; i++) {
+        if (idAlice[i] != idBob[i]) {
+          return "IDs don't match!";
+        }
+      }
+
+      if (recoveryAlice != recoveryBob) {
+        return "Recovery strings don't match!";
+      }
+
       // return "success" or return early with error message string
       return "success";
     } catch (e, s) {
@@ -77,8 +115,4 @@ abstract class FrostSampleRunner {
       return e.toString();
     }
   }
-
-  static Future<String> run() async {
-    return await compute(_run, null);
-  }
 }
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 97a0cbc..61682dc 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -54,7 +54,7 @@ class _ContentState extends State<Content> {
   @override
   Widget build(BuildContext context) {
     const textStyle = TextStyle(fontSize: 25);
-    const spacerSmall = SizedBox(height: 10);
+    const spacerSmall = SizedBox(height: 30);
     return Container(
       padding: const EdgeInsets.all(10),
       child: Column(
@@ -67,11 +67,15 @@ class _ContentState extends State<Content> {
                 enableButton = false;
               });
               showDialog(
-                  barrierDismissible: false,
-                  context: context,
-                  builder: (context) =>
-                      const AlertDialog(title: Text("Running")));
-              result = await FrostSampleRunner.run();
+                barrierDismissible: false,
+                context: context,
+                builder: (context) => const AlertDialog(
+                  title: Text(
+                    "Running",
+                  ),
+                ),
+              );
+              result = await FrostSampleRunner.runKeygen();
               if (mounted) {
                 Navigator.of(context).pop();
                 setState(() {
@@ -79,13 +83,14 @@ class _ContentState extends State<Content> {
                 });
               }
             },
-            child: const Text("RUN"),
+            child: const Text(
+              "RUN SIMPLE KEYGEN TEST",
+              style: textStyle,
+            ),
           ),
           spacerSmall,
-          spacerSmall,
-          spacerSmall,
           Text(
-            'Result: ${result.toString()}',
+            'Keygen result: ${result.toString()}',
             style: textStyle,
             textAlign: TextAlign.center,
           ),
diff --git a/lib/util.dart b/lib/util.dart
index cdcf359..5fe4fb4 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -14,6 +14,7 @@ class FrostdartException implements Exception {
 
 const int SALT_BYTES_LENGTH = 32;
 const int HASH_BYTES_LENGTH = 32;
+const int MULTISIG_ID_LENGTH = 32;
 const int SUCCESS = 0;
 
 enum Language {

From 47de72103ce10561352d9df871094054751218aa Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 09:19:35 -0600
Subject: [PATCH 18/49] remove unnecessary param and check lengths match

---
 lib/frostdart.dart | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index ed4257c..57fbc5a 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -390,12 +390,15 @@ int signFeePerWeight({
 ffi.Pointer<SignConfigRes> newSignConfig({
   required int network,
   required List<Output> outputs,
-  required int payments,
   required List<String> paymentAddresses,
   required List<int> paymentAmounts,
   required String change,
   required int feePerWeight,
 }) {
+  if (paymentAddresses.length != paymentAmounts.length) {
+    throw Exception("paymentAddresses.length != paymentAmounts.length");
+  }
+
   final outputsPointer = calloc<PortableOutput>(outputs.length);
   for (int i = 0; i < outputs.length; i++) {
     outputsPointer[i].vout = outputs[i].vout;
@@ -442,7 +445,7 @@ ffi.Pointer<SignConfigRes> newSignConfig({
     network,
     outputsPointer,
     outputs.length,
-    payments,
+    paymentAddresses.length,
     paymentAddressesPointer,
     paymentAmountsPointer,
     stringViewPointer.ref,

From cbdcd11408589fed983043ba04fc94bf144ffdc1 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 09:35:49 -0600
Subject: [PATCH 19/49] array access fix

---
 lib/frostdart.dart | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 57fbc5a..6c4c9cd 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -405,17 +405,16 @@ ffi.Pointer<SignConfigRes> newSignConfig({
     outputsPointer[i].value = outputs[i].value;
 
     final hashLength = outputs[i].hash.length;
-    final hashArr = ffi.Array<ffi.Uint8>(hashLength);
     for (int j = 0; j < hashLength; j++) {
-      hashArr[j] = outputs[i].hash[j];
+      outputsPointer[i].hash[j] = outputs[i].hash[j];
     }
-    outputsPointer[i].hash = hashArr;
     outputsPointer[i].script_pubkey_len = outputs[i].scriptPubKey.length;
 
     outputsPointer[i].script_pubkey =
         calloc<ffi.Uint8>(outputsPointer[i].script_pubkey_len);
     for (int j = 0; j < outputsPointer[i].script_pubkey_len; j++) {
-      outputsPointer[i].script_pubkey.elementAt(j).value = outputs[i].hash[j];
+      outputsPointer[i].script_pubkey.elementAt(j).value =
+          outputs[i].scriptPubKey[j];
     }
   }
 

From 5e2d0ec29c06a2e46a9d3cc97a3f070567b3f0c5 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 10:38:46 -0600
Subject: [PATCH 20/49] updated serai ref and bindings

---
 lib/frostdart_bindings_generated.dart | 32 +++++++++++++++++++++++++++
 src/serai                             |  2 +-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 1333e40..7dc60d4 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -300,6 +300,38 @@ class FrostdartBindings {
   late final _deserialize_keys = _deserialize_keysPtr
       .asFunction<CResult_ThresholdKeysWrapper Function(StringView)>();
 
+  OwnedString address_for_keys(
+    int network,
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+  ) {
+    return _address_for_keys(
+      network,
+      keys,
+    );
+  }
+
+  late final _address_for_keysPtr = _lookup<
+      ffi.NativeFunction<
+          OwnedString Function(ffi.Int32,
+              ffi.Pointer<ThresholdKeysWrapper>)>>('address_for_keys');
+  late final _address_for_keys = _address_for_keysPtr.asFunction<
+      OwnedString Function(int, ffi.Pointer<ThresholdKeysWrapper>)>();
+
+  OwnedString script_pub_key_for_keys(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+  ) {
+    return _script_pub_key_for_keys(
+      keys,
+    );
+  }
+
+  late final _script_pub_key_for_keysPtr = _lookup<
+      ffi.NativeFunction<
+          OwnedString Function(
+              ffi.Pointer<ThresholdKeysWrapper>)>>('script_pub_key_for_keys');
+  late final _script_pub_key_for_keys = _script_pub_key_for_keysPtr
+      .asFunction<OwnedString Function(ffi.Pointer<ThresholdKeysWrapper>)>();
+
   ffi.Pointer<ffi.Uint8> output_hash(
     ffi.Pointer<OwnedPortableOutput> self,
   ) {
diff --git a/src/serai b/src/serai
index 0298704..ff471d7 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 02987043d2c097ffcc3bea8c1dce67086707d1bc
+Subproject commit ff471d740f7d307dd839322ef2fac6c72960f446

From 8516dddcd4ec93715767afda2de99ac47ca3eb1f Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 16:02:59 -0600
Subject: [PATCH 21/49] Correct header

---
 lib/frostdart_bindings_generated.dart | 44 ++++++++++-----------
 lib/util.dart                         | 55 ++++++++++++++++-----------
 src/serai                             |  2 +-
 3 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 7dc60d4..18f66ad 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -844,46 +844,46 @@ const int LANGUAGE_KOREAN = 7;
 
 const int LANGUAGE_SPANISH = 8;
 
-const int UNKNOWN_ERROR = 101;
+const int UNKNOWN_ERROR = 21;
 
-const int INVALID_ENCODING_ERROR = 102;
+const int INVALID_ENCODING_ERROR = 22;
 
-const int INVALID_PARTICIPANT_ERROR = 103;
+const int INVALID_PARTICIPANT_ERROR = 23;
 
-const int INVALID_SHARE_ERROR = 104;
+const int INVALID_SHARE_ERROR = 24;
 
-const int ZERO_PARAMETER_ERROR = 201;
+const int ZERO_PARAMETER_ERROR = 41;
 
-const int INVALID_THRESHOLD_ERROR = 202;
+const int INVALID_THRESHOLD_ERROR = 42;
 
-const int INVALID_NAME_ERROR = 203;
+const int INVALID_NAME_ERROR = 43;
 
-const int UNKNOWN_LANGUAGE_ERROR = 204;
+const int UNKNOWN_LANGUAGE_ERROR = 44;
 
-const int INVALID_SEED_ERROR = 205;
+const int INVALID_SEED_ERROR = 45;
 
-const int INVALID_AMOUNT_OF_COMMITMENTS_ERROR = 206;
+const int INVALID_AMOUNT_OF_COMMITMENTS_ERROR = 46;
 
-const int INVALID_COMMITMENTS_ERROR = 207;
+const int INVALID_COMMITMENTS_ERROR = 47;
 
-const int INVALID_AMOUNT_OF_SHARES_ERROR = 208;
+const int INVALID_AMOUNT_OF_SHARES_ERROR = 48;
 
-const int INVALID_OUTPUT_ERROR = 301;
+const int INVALID_OUTPUT_ERROR = 61;
 
-const int INVALID_ADDRESS_ERROR = 302;
+const int INVALID_ADDRESS_ERROR = 62;
 
-const int INVALID_NETWORK_ERROR = 303;
+const int INVALID_NETWORK_ERROR = 63;
 
-const int NO_INPUTS_ERROR = 304;
+const int NO_INPUTS_ERROR = 64;
 
-const int NO_OUTPUTS_ERROR = 305;
+const int NO_OUTPUTS_ERROR = 65;
 
-const int DUST_ERROR = 306;
+const int DUST_ERROR = 66;
 
-const int NOT_ENOUGH_FUNDS_ERROR = 307;
+const int NOT_ENOUGH_FUNDS_ERROR = 67;
 
-const int TOO_LARGE_TRANSACTION_ERROR = 308;
+const int TOO_LARGE_TRANSACTION_ERROR = 68;
 
-const int WRONG_KEYS_ERROR = 309;
+const int WRONG_KEYS_ERROR = 69;
 
-const int INVALID_PREPROCESS_ERROR = 310;
+const int INVALID_PREPROCESS_ERROR = 70;
diff --git a/lib/util.dart b/lib/util.dart
index 5fe4fb4..695aef6 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -35,49 +35,49 @@ enum Language {
 
 String getErrorName(int errorCode) {
   switch (errorCode) {
-    case 101:
+    case UNKNOWN_ERROR:
       return 'UNKNOWN_ERROR';
-    case 102:
+    case INVALID_ENCODING_ERROR:
       return 'INVALID_ENCODING_ERROR';
-    case 103:
+    case INVALID_PARTICIPANT_ERROR:
       return 'INVALID_PARTICIPANT_ERROR';
-    case 104:
+    case INVALID_SHARE_ERROR:
       return 'INVALID_SHARE_ERROR';
-    case 201:
+    case ZERO_PARAMETER_ERROR:
       return 'ZERO_PARAMETER_ERROR';
-    case 202:
+    case INVALID_THRESHOLD_ERROR:
       return 'INVALID_THRESHOLD_ERROR';
-    case 203:
+    case INVALID_NAME_ERROR:
       return 'INVALID_NAME_ERROR';
-    case 204:
+    case UNKNOWN_LANGUAGE_ERROR:
       return 'UNKNOWN_LANGUAGE_ERROR';
-    case 205:
+    case INVALID_SEED_ERROR:
       return 'INVALID_SEED_ERROR';
-    case 206:
+    case INVALID_AMOUNT_OF_COMMITMENTS_ERROR:
       return 'INVALID_AMOUNT_OF_COMMITMENTS_ERROR';
-    case 207:
+    case INVALID_COMMITMENTS_ERROR:
       return 'INVALID_COMMITMENTS_ERROR';
-    case 208:
+    case INVALID_AMOUNT_OF_SHARES_ERROR:
       return 'INVALID_AMOUNT_OF_SHARES_ERROR';
-    case 301:
+    case INVALID_OUTPUT_ERROR:
       return 'INVALID_OUTPUT_ERROR';
-    case 302:
+    case INVALID_ADDRESS_ERROR:
       return 'INVALID_ADDRESS_ERROR';
-    case 303:
+    case INVALID_NETWORK_ERROR:
       return 'INVALID_NETWORK_ERROR';
-    case 304:
+    case NO_INPUTS_ERROR:
       return 'NO_INPUTS_ERROR';
-    case 305:
+    case NO_OUTPUTS_ERROR:
       return 'NO_OUTPUTS_ERROR';
-    case 306:
+    case DUST_ERROR:
       return 'DUST_ERROR';
-    case 307:
+    case NOT_ENOUGH_FUNDS_ERROR:
       return 'NOT_ENOUGH_FUNDS_ERROR';
-    case 308:
+    case TOO_LARGE_TRANSACTION_ERROR:
       return 'TOO_LARGE_TRANSACTION_ERROR';
-    case 309:
+    case WRONG_KEYS_ERROR:
       return 'WRONG_KEYS_ERROR';
-    case 310:
+    case INVALID_PREPROCESS_ERROR:
       return 'INVALID_PREPROCESS_ERROR';
     default:
       return 'UNKNOWN ERROR CODE "$errorCode"';
@@ -92,3 +92,14 @@ extension OwnedStringExt on OwnedString {
     return string;
   }
 }
+
+List<int> hexStringToList(String hexString) {
+  final length = hexString.length;
+  List<int> result = [];
+  for (int i = 0; i < length; i += 2) {
+    String hexByte = hexString.substring(i, i + 2);
+    int byteValue = int.parse(hexByte, radix: 16);
+    result.add(byteValue);
+  }
+  return result;
+}
diff --git a/src/serai b/src/serai
index ff471d7..ac28bbc 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit ff471d740f7d307dd839322ef2fac6c72960f446
+Subproject commit ac28bbc0b4df24715ad3cac4cfc8fe2e35137686

From c149bb2593e81e37175064c13f6ecb566ba9c36b Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 16:15:28 -0600
Subject: [PATCH 22/49] added new wrappers for new bindings

---
 lib/frostdart.dart | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 6c4c9cd..9146ccf 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -358,6 +358,25 @@ String signPaymentAddress({
   return string;
 }
 
+String addressForKeys({
+  required int network,
+  required ffi.Pointer<ThresholdKeysWrapper> keys,
+}) {
+  final ownedString = _bindings.address_for_keys(network, keys);
+
+  return ownedString.toDartString();
+}
+
+Uint8List scriptPubKeyForKeys({
+  required ffi.Pointer<ThresholdKeysWrapper> keys,
+}) {
+  final ownedString = _bindings.script_pub_key_for_keys(keys);
+
+  final bytes = ownedString.ptr.asTypedList(ownedString.len);
+
+  return bytes;
+}
+
 int signPaymentAmount({
   required ffi.Pointer<SignConfig> signConfigPointer,
   required int index,

From 247db1323335b147520535d0576230b41b41b165 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 16:17:52 -0600
Subject: [PATCH 23/49] WIP signing example

---
 example/lib/frost_sample_run.dart | 144 +++++++++++++++++++++++++++++-
 example/lib/main.dart             |  89 +++++++++++++-----
 2 files changed, 205 insertions(+), 28 deletions(-)

diff --git a/example/lib/frost_sample_run.dart b/example/lib/frost_sample_run.dart
index f346384..f59ee86 100644
--- a/example/lib/frost_sample_run.dart
+++ b/example/lib/frost_sample_run.dart
@@ -2,22 +2,149 @@ import 'dart:ffi';
 
 import 'package:flutter/foundation.dart';
 import 'package:frostdart/frostdart.dart';
+import 'package:frostdart/frostdart_bindings_generated.dart';
+import 'package:frostdart/output.dart';
 import 'package:frostdart/util.dart';
 
 abstract class FrostSampleRunner {
+  static Future<String> runSign() async {
+    return await compute(_runSign, null);
+  }
+
+  static String _runSign(int? dummy) {
+    try {
+      const network = Network.Regtest;
+
+      final deserializedKeysAlice = deserializeKeys(
+          keys:
+              "09000000736563703235366b310100020001003e328d631524f038ab56c2de35"
+              "a94fb516642098e12e5eef28a07eb5e0d9b682036a7aa3a78f3f5cf6e210"
+              "9a4885239b97aa945d8c3a4e560ad2067074825122dd036a7aa3a78f3f5c"
+              "f6e2109a4885239b97aa945d8c3a4e560ad2067074825122dd");
+      final deserializedKeysBob = deserializeKeys(
+          keys:
+              "09000000736563703235366b310100020002003e328d631524f038ab56c2de35"
+              "a94fb516642098e12e5eef28a07eb5e0d9b682036a7aa3a78f3f5cf6e210"
+              "9a4885239b97aa945d8c3a4e560ad2067074825122dd036a7aa3a78f3f5c"
+              "f6e2109a4885239b97aa945d8c3a4e560ad2067074825122dd");
+
+      final address =
+          addressForKeys(network: network, keys: deserializedKeysAlice);
+
+      debugPrint("Address: $address");
+
+      final signConfigRes = newSignConfig(
+        network: network,
+        outputs: [
+          Output(
+            hash: Uint8List.fromList(
+              hexStringToList(
+                "1993649f48a6a6053e574c1be9eb607728c6e39b7d3fea2206a2af0f6131c74c",
+              ),
+            ),
+            vout: 1,
+            value: 200000000,
+            scriptPubKey: Uint8List.fromList(
+              hexStringToList(
+                "5120105968eaa94d798d554d76a381fd65060696c3685ca1434e4d3ba82bd3f5bde0",
+              ),
+            ),
+          ),
+        ],
+        paymentAddresses: [
+          "bcrt1qdc89v44888fjwus4wke8kppj6043h9698wf8uv",
+        ],
+        paymentAmounts: [500000],
+        change: "bcrt1qdc89v44888fjwus4wke8kppj6043h9698wf8uv",
+        feePerWeight: 3000,
+      );
+
+      debugPrint("created sign config (ptr address = ${signConfigRes.address}");
+
+      final String encodedConfig = signConfigRes.ref.encoded.toDartString();
+
+      final signConfig = decodeSignConfig(
+        network: network,
+        encodedSignConfig: encodedConfig,
+      );
+
+      debugPrint("decoded config finished");
+
+      final attemptSignResAlice = attemptSign(
+        thresholdKeysWrapperPointer: deserializedKeysAlice,
+        signConfigPointer: signConfigRes.ref.config,
+      );
+      final attemptSignResBob = attemptSign(
+        thresholdKeysWrapperPointer: deserializedKeysBob,
+        signConfigPointer: signConfig,
+      );
+      debugPrint("attemptSign finished");
+
+      final alicePre = attemptSignResAlice.ref.preprocess.toDartString();
+      debugPrint("alicePre: $alicePre");
+
+      final bobPre = attemptSignResBob.ref.preprocess.toDartString();
+      debugPrint("bobPre: $bobPre");
+
+      final preprocesses = [
+        alicePre,
+        bobPre,
+      ];
+      debugPrint("preprocesses: $preprocesses");
+
+      final continueSignResAlice = continueSign(
+        machine: attemptSignResAlice.ref.machine,
+        preprocesses: preprocesses,
+      );
+      final continueSignResBob = continueSign(
+        machine: attemptSignResBob.ref.machine,
+        preprocesses: preprocesses,
+      );
+      debugPrint("continueSign finished");
+
+      final contPreAlice = continueSignResAlice.ref.preprocess.toDartString();
+      debugPrint("contPreAlice: $contPreAlice");
+      final contPreBob = continueSignResBob.ref.preprocess.toDartString();
+      debugPrint("contPreBob: $contPreBob");
+
+      final completeSignResAlice = completeSign(
+        machine: continueSignResAlice.ref.machine,
+        shares: [
+          contPreAlice,
+          contPreBob,
+        ],
+      );
+      final completeSignResBob = completeSign(
+        machine: continueSignResBob.ref.machine,
+        shares: [
+          contPreAlice,
+          contPreBob,
+        ],
+      );
+      debugPrint("completeSign finished");
+
+      // return "success" or return early with error message string
+      return "success";
+    } catch (e, s) {
+      debugPrint("run error: $e\n$s");
+      return e.toString();
+    }
+  }
+
   static Future<String> runKeygen() async {
     return await compute(_runKeygen, null);
   }
 
   static String _runKeygen(int? dummy) {
     try {
+      const participants = [
+        "alice",
+        "bob",
+      ];
       final sharedMultisigConfig = newMultisigConfig(
         name: "alice",
         threshold: 1,
-        participants: [
-          "alice",
-          "bob",
-        ],
+        participants: participants,
       );
 
       final encodedConfig = sharedMultisigConfig.ref.encoded.toDartString();
@@ -108,6 +235,15 @@ abstract class FrostSampleRunner {
         return "Recovery strings don't match!";
       }
 
+      final serializedKeysAlice =
+          serializeKeys(keys: completeGenAlice.ref.keys);
+      debugPrint("serializedKeysAlice: $serializedKeysAlice");
+      final serializedKeysBob = serializeKeys(keys: completeGenBob.ref.keys);
+      debugPrint("serializedKeysBob: $serializedKeysBob");
+
+      debugPrint(
+          "serializedKeys match: ${serializedKeysBob == serializedKeysAlice}");
+
       // return "success" or return early with error message string
       return "success";
     } catch (e, s) {
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 61682dc..6e168c2 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -41,7 +41,8 @@ class Content extends StatefulWidget {
 }
 
 class _ContentState extends State<Content> {
-  String? result;
+  String? resultKeygen;
+  String? resultSign;
 
   late bool enableButton;
 
@@ -54,7 +55,7 @@ class _ContentState extends State<Content> {
   @override
   Widget build(BuildContext context) {
     const textStyle = TextStyle(fontSize: 25);
-    const spacerSmall = SizedBox(height: 30);
+    const spacerSmall = SizedBox(height: 20);
     return Container(
       padding: const EdgeInsets.all(10),
       child: Column(
@@ -62,27 +63,29 @@ class _ContentState extends State<Content> {
         mainAxisAlignment: MainAxisAlignment.center,
         children: [
           TextButton(
-            onPressed: () async {
-              setState(() {
-                enableButton = false;
-              });
-              showDialog(
-                barrierDismissible: false,
-                context: context,
-                builder: (context) => const AlertDialog(
-                  title: Text(
-                    "Running",
-                  ),
-                ),
-              );
-              result = await FrostSampleRunner.runKeygen();
-              if (mounted) {
-                Navigator.of(context).pop();
-                setState(() {
-                  enableButton = true;
-                });
-              }
-            },
+            onPressed: !enableButton
+                ? null
+                : () async {
+                    setState(() {
+                      enableButton = false;
+                    });
+                    showDialog(
+                      barrierDismissible: false,
+                      context: context,
+                      builder: (context) => const AlertDialog(
+                        title: Text(
+                          "Running",
+                        ),
+                      ),
+                    );
+                    resultKeygen = await FrostSampleRunner.runKeygen();
+                    if (mounted) {
+                      Navigator.of(context).pop();
+                      setState(() {
+                        enableButton = true;
+                      });
+                    }
+                  },
             child: const Text(
               "RUN SIMPLE KEYGEN TEST",
               style: textStyle,
@@ -90,7 +93,45 @@ class _ContentState extends State<Content> {
           ),
           spacerSmall,
           Text(
-            'Keygen result: ${result.toString()}',
+            'Keygen result: $resultKeygen',
+            style: textStyle,
+            textAlign: TextAlign.center,
+          ),
+          spacerSmall,
+          spacerSmall,
+          spacerSmall,
+          TextButton(
+            onPressed: enableButton
+                ? () async {
+                    setState(() {
+                      enableButton = false;
+                    });
+                    showDialog(
+                      barrierDismissible: false,
+                      context: context,
+                      builder: (context) => const AlertDialog(
+                        title: Text(
+                          "Running",
+                        ),
+                      ),
+                    );
+                    resultSign = await FrostSampleRunner.runSign();
+                    if (mounted) {
+                      Navigator.of(context).pop();
+                      setState(() {
+                        enableButton = true;
+                      });
+                    }
+                  }
+                : null,
+            child: const Text(
+              "RUN SIMPLE SIGN TEST",
+              style: textStyle,
+            ),
+          ),
+          spacerSmall,
+          Text(
+            'Sign result: ${resultSign.toString()}',
             style: textStyle,
             textAlign: TextAlign.center,
           ),

From a20d47d448638e5e1d0192ba971e81fa63572c1a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 16:38:04 -0600
Subject: [PATCH 24/49] fix double free

---
 lib/frostdart.dart | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 9146ccf..cd94872 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -570,8 +570,6 @@ String completeSign({
     shares.length,
   );
 
-  calloc.free(sharesPointer);
-
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {

From 39f810081cacb223b66ac891f0c37fdf1aef1dbb Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 4 Aug 2023 16:38:35 -0600
Subject: [PATCH 25/49] simple signing example

---
 example/lib/frost_sample_run.dart | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/example/lib/frost_sample_run.dart b/example/lib/frost_sample_run.dart
index f59ee86..8399772 100644
--- a/example/lib/frost_sample_run.dart
+++ b/example/lib/frost_sample_run.dart
@@ -86,19 +86,19 @@ abstract class FrostSampleRunner {
       final bobPre = attemptSignResBob.ref.preprocess.toDartString();
       debugPrint("bobPre: $bobPre");
 
-      final preprocesses = [
-        alicePre,
-        bobPre,
-      ];
-      debugPrint("preprocesses: $preprocesses");
-
       final continueSignResAlice = continueSign(
         machine: attemptSignResAlice.ref.machine,
-        preprocesses: preprocesses,
+        preprocesses: [
+          "",
+          bobPre,
+        ],
       );
       final continueSignResBob = continueSign(
         machine: attemptSignResBob.ref.machine,
-        preprocesses: preprocesses,
+        preprocesses: [
+          alicePre,
+          "",
+        ],
       );
       debugPrint("continueSign finished");
 
@@ -110,7 +110,7 @@ abstract class FrostSampleRunner {
       final completeSignResAlice = completeSign(
         machine: continueSignResAlice.ref.machine,
         shares: [
-          contPreAlice,
+          "",
           contPreBob,
         ],
       );
@@ -118,11 +118,17 @@ abstract class FrostSampleRunner {
         machine: continueSignResBob.ref.machine,
         shares: [
           contPreAlice,
-          contPreBob,
+          "",
         ],
       );
       debugPrint("completeSign finished");
 
+      debugPrint("completeSignResAlice: $completeSignResAlice");
+      debugPrint("completeSignResBob: $completeSignResBob");
+
+      debugPrint(
+          "completeSignResBob == completeSignResAlice:: ${completeSignResBob == completeSignResAlice}");
+
       // return "success" or return early with error message string
       return "success";
     } catch (e, s) {

From 835c1e404bf57d9021464563334f49420bd9c049 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 8 Aug 2023 10:02:29 -0600
Subject: [PATCH 26/49] update build script to use rust 1.71.0

---
 scripts/linux/build_all.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh
index b86eeb5..cc6ec8d 100755
--- a/scripts/linux/build_all.sh
+++ b/scripts/linux/build_all.sh
@@ -9,10 +9,10 @@ rm -rf "$ROOT_DIR"/src/serai/target
 cd "$ROOT_DIR"/src/serai/hrf || exit
 if [ "$IS_ARM" = true ]  ; then
     echo "Building arm frostdart"
-    cargo build --target aarch64-unknown-linux-gnu --release --lib
+    cargo +1.71.0 build --target aarch64-unknown-linux-gnu --release --lib
     cp ../target/aarch64-unknown-linux-gnu/release/libhrf_api.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
 else
     echo "Building x86_64 frostdart"
-    cargo build --target x86_64-unknown-linux-gnu --release --lib
+    cargo +1.71.0 build --target x86_64-unknown-linux-gnu --release --lib
     cp ../target/x86_64-unknown-linux-gnu/release/libhrf_api.so "$ROOT_DIR"/scripts/linux/build/frostdart.so
 fi
\ No newline at end of file

From 7745395d8bdda90fc2cd382f085df55c5b3a8505 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 8 Aug 2023 12:47:03 -0600
Subject: [PATCH 27/49] android build

---
 android/build.gradle                          | 35 ++++++------
 .../com/example/frostdart/FrostdartPlugin.kt  | 35 ++++++++++++
 .../android/app/src/debug/AndroidManifest.xml |  3 +-
 .../android/app/src/main/AndroidManifest.xml  |  3 +-
 .../app/src/profile/AndroidManifest.xml       |  3 +-
 example/ios/Flutter/Debug.xcconfig            |  1 +
 example/ios/Flutter/Release.xcconfig          |  1 +
 .../contents.xcworkspacedata                  |  3 ++
 scripts/android/.cargo/config                 |  2 +
 scripts/android/build_all.sh                  | 53 +++++++++++++++++++
 10 files changed, 116 insertions(+), 23 deletions(-)
 create mode 100644 android/src/main/kotlin/com/example/frostdart/FrostdartPlugin.kt
 create mode 100644 scripts/android/.cargo/config
 create mode 100755 scripts/android/build_all.sh

diff --git a/android/build.gradle b/android/build.gradle
index 4ef4c96..c65296e 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -4,14 +4,15 @@ group 'com.example.frostdart'
 version '1.0'
 
 buildscript {
+    ext.kotlin_version = '1.7.10'
     repositories {
         google()
         mavenCentral()
     }
 
     dependencies {
-        // The Android Gradle Plugin knows how to build native code with the NDK.
         classpath 'com.android.tools.build:gradle:7.3.0'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
     }
 }
 
@@ -23,37 +24,31 @@ rootProject.allprojects {
 }
 
 apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
 
 android {
     // Bumping the plugin compileSdkVersion requires all clients of this plugin
     // to bump the version in their app.
     compileSdkVersion 31
 
-    // Bumping the plugin ndkVersion requires all clients of this plugin to bump
-    // the version in their app and to download a newer version of the NDK.
-    ndkVersion "23.1.7779620"
-
-    // Invoke the shared CMake build with the Android Gradle Plugin.
-    externalNativeBuild {
-        cmake {
-            path "../src/CMakeLists.txt"
-
-            // The default CMake version for the Android Gradle Plugin is 3.10.2.
-            // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
-            //
-            // The Flutter tooling requires that developers have CMake 3.10 or later
-            // installed. You should not increase this version, as doing so will cause
-            // the plugin to fail to compile for some customers of the plugin.
-            // version "3.10.2"
-        }
-    }
-
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
 
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+
     defaultConfig {
         minSdkVersion 16
     }
 }
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/android/src/main/kotlin/com/example/frostdart/FrostdartPlugin.kt b/android/src/main/kotlin/com/example/frostdart/FrostdartPlugin.kt
new file mode 100644
index 0000000..cf19261
--- /dev/null
+++ b/android/src/main/kotlin/com/example/frostdart/FrostdartPlugin.kt
@@ -0,0 +1,35 @@
+package com.example.flutter_libepiccash
+
+import androidx.annotation.NonNull
+
+import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+import io.flutter.plugin.common.MethodChannel.Result
+
+/** FlutterLibepiccashPlugin */
+class FrostdartPlugin: FlutterPlugin, MethodCallHandler {
+  /// The MethodChannel that will the communication between Flutter and native Android
+  ///
+  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
+  /// when the Flutter Engine is detached from the Activity
+  private lateinit var channel : MethodChannel
+
+  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
+    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "frostdart")
+    channel.setMethodCallHandler(this)
+  }
+
+  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
+    if (call.method == "getPlatformVersion") {
+      result.success("Android ${android.os.Build.VERSION.RELEASE}")
+    } else {
+      result.notImplemented()
+    }
+  }
+
+  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
+    channel.setMethodCallHandler(null)
+  }
+}
diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml
index 399f698..ab4c41f 100644
--- a/example/android/app/src/debug/AndroidManifest.xml
+++ b/example/android/app/src/debug/AndroidManifest.xml
@@ -1,4 +1,5 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.frostdart_example">
     <!-- The INTERNET permission is required for development. Specifically,
          the Flutter tool needs it to communicate with the running application
          to allow setting breakpoints, to provide hot reload, etc.
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index a35d6d2..ab3afe0 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.frostdart_example">
     <application
         android:label="frostdart_example"
         android:name="${applicationName}"
diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml
index 399f698..ab4c41f 100644
--- a/example/android/app/src/profile/AndroidManifest.xml
+++ b/example/android/app/src/profile/AndroidManifest.xml
@@ -1,4 +1,5 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.frostdart_example">
     <!-- The INTERNET permission is required for development. Specifically,
          the Flutter tool needs it to communicate with the running application
          to allow setting breakpoints, to provide hot reload, etc.
diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig
index 592ceee..ec97fc6 100644
--- a/example/ios/Flutter/Debug.xcconfig
+++ b/example/ios/Flutter/Debug.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
 #include "Generated.xcconfig"
diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig
index 592ceee..c4855bf 100644
--- a/example/ios/Flutter/Release.xcconfig
+++ b/example/ios/Flutter/Release.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
 #include "Generated.xcconfig"
diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata
index 1d526a1..21a3cc1 100644
--- a/example/ios/Runner.xcworkspace/contents.xcworkspacedata
+++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -4,4 +4,7 @@
    <FileRef
       location = "group:Runner.xcodeproj">
    </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
 </Workspace>
diff --git a/scripts/android/.cargo/config b/scripts/android/.cargo/config
new file mode 100644
index 0000000..fc58020
--- /dev/null
+++ b/scripts/android/.cargo/config
@@ -0,0 +1,2 @@
+[target.aarch64-linux-android]
+linker = "replaceme"
\ No newline at end of file
diff --git a/scripts/android/build_all.sh b/scripts/android/build_all.sh
new file mode 100755
index 0000000..d8ebdef
--- /dev/null
+++ b/scripts/android/build_all.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+export API=25
+
+WORKDIR="$(pwd)/"build
+export WORKDIR
+
+ROOT_DIR="$(pwd)/../.."
+
+mkdir -p build
+
+export ANDROID_NDK_ZIP=${WORKDIR}/android-ndk-r25c.zip
+export ANDROID_NDK_ROOT=${WORKDIR}/android-ndk-r25c
+ANDROID_NDK_SHA256="53af80a1cce9144025b81c78c8cd556bff42bd0e"
+if [ ! -e "$ANDROID_NDK_ZIP" ]; then
+  curl https://dl.google.com/android/repository/android-ndk-r25c-linux.zip -o "${ANDROID_NDK_ZIP}"
+fi
+echo $ANDROID_NDK_SHA256 "$ANDROID_NDK_ZIP" | sha1sum -c || exit 1
+unzip "$ANDROID_NDK_ZIP" -d "$WORKDIR"
+
+export ANDROID_NDK_HOME=$ANDROID_NDK_ROOT
+
+export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
+export TARGET=aarch64-linux-android
+export API=33
+export AR=$TOOLCHAIN/bin/llvm-ar
+export CC=$TOOLCHAIN/bin/$TARGET$API-clang
+export AS=$CC
+export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
+export LD=$TOOLCHAIN/bin/ld
+export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
+export STRIP=$TOOLCHAIN/bin/llvm-strip
+export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
+export PATH=$PATH:$TOOLCHAIN/bin
+
+# inject absolute linker path into cargo config
+LINKER_PATH="$TOOLCHAIN"/bin/aarch64-linux-android33-clang
+cp -R .cargo build/
+sed -i "s#replaceme#${LINKER_PATH}#g" build/.cargo/config
+
+cp -R "$ROOT_DIR"/src/serai build/
+cd build/serai/hrf || exit
+
+# inject vendored openssl required for android cross compilation
+sed -i "s/\[dependencies\]/\[dependencies\]\\
+openssl = { version = \"0.10\", features = [\"vendored\"] }/" Cargo.toml
+
+rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
+cargo ndk -t armeabi-v7a -t arm64-v8a -t x86_64 -o "$ROOT_DIR"/android/src/main/jniLibs build --release
+
+mv "$ROOT_DIR"/android/src/main/jniLibs/armeabi-v7a/libhrf_api.so "$ROOT_DIR"/android/src/main/jniLibs/armeabi-v7a/frostdart.so
+mv "$ROOT_DIR"/android/src/main/jniLibs/arm64-v8a/libhrf_api.so "$ROOT_DIR"/android/src/main/jniLibs/arm64-v8a/frostdart.so
+mv "$ROOT_DIR"/android/src/main/jniLibs/x86_64/libhrf_api.so "$ROOT_DIR"/android/src/main/jniLibs/x86_64/frostdart.so

From 903da66406168e45de43744cf8d4b11e493f8446 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 8 Aug 2023 12:47:53 -0600
Subject: [PATCH 28/49] update gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 37e1713..59d1dcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,5 @@ build/
 
 .flutter-plugins
 .flutter-plugins-dependencies
+
+android/src/main/jniLibs/

From 844c98636693e6f9c22a84b0359f415d56f9f4c7 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 8 Aug 2023 12:49:02 -0600
Subject: [PATCH 29/49] update serai ref

---
 src/serai | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serai b/src/serai
index ac28bbc..facbd19 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit ac28bbc0b4df24715ad3cac4cfc8fe2e35137686
+Subproject commit facbd19bc1ebd3b547afaef972b194f153121191

From 5ce4b3f6906de4e3cca83b7cbb5f99a1673c7073 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 10 Aug 2023 13:53:38 -0600
Subject: [PATCH 30/49] linux cmakelists fix

---
 linux/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt
index 2e72324..75accab 100644
--- a/linux/CMakeLists.txt
+++ b/linux/CMakeLists.txt
@@ -137,7 +137,7 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}
 install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
         COMPONENT Runtime)
 
-install(FILES "${CMAKE_SOURCE_DIR}/../../scripts/linux/build/frostdart.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/frostdart.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
         COMPONENT Runtime)
 
 foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})

From 7e008d14c6a726e718f606b090e361bbfcd101af Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 15 Aug 2023 11:44:42 -0600
Subject: [PATCH 31/49] fix ffi wrapper call

---
 lib/frostdart.dart | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index cd94872..9545216 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -367,14 +367,12 @@ String addressForKeys({
   return ownedString.toDartString();
 }
 
-Uint8List scriptPubKeyForKeys({
+String scriptPubKeyForKeys({
   required ffi.Pointer<ThresholdKeysWrapper> keys,
 }) {
   final ownedString = _bindings.script_pub_key_for_keys(keys);
 
-  final bytes = ownedString.ptr.asTypedList(ownedString.len);
-
-  return bytes;
+  return ownedString.toDartString();
 }
 
 int signPaymentAmount({

From 65ca70ee31499b45a1709999c6e9f0492a7f5c0e Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 16 Aug 2023 16:09:13 -0600
Subject: [PATCH 32/49] fix func signature

---
 lib/frostdart.dart | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 9545216..031af6b 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -399,7 +399,6 @@ String signChange({
 
 int signFeePerWeight({
   required ffi.Pointer<SignConfig> signConfigPointer,
-  required int index,
 }) {
   return _bindings.sign_fee_per_weight(signConfigPointer);
 }

From 819f4027ee74d7c4ebb805a19e9b99aed53ccfcc Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Aug 2023 12:46:29 -0600
Subject: [PATCH 33/49] add toString

---
 lib/output.dart | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/output.dart b/lib/output.dart
index fc1cb51..58bdece 100644
--- a/lib/output.dart
+++ b/lib/output.dart
@@ -12,4 +12,12 @@ class Output {
     required this.value,
     required this.scriptPubKey,
   });
+
+  @override
+  String toString() => 'Output{'
+      'hash: $hash, '
+      'vout: $vout, '
+      'value: $value, '
+      'scriptPubKey: $scriptPubKey'
+      '}';
 }

From e26c199466df7cb3dad8d2397e5c1e1967c639e5 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Aug 2023 14:29:29 -0600
Subject: [PATCH 34/49] pass config in by string

---
 lib/frostdart.dart | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 031af6b..b4d9d0f 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -75,8 +75,9 @@ String multisigParticipant({
 }
 
 Uint8List multisigSalt({
-  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+  required String multisigConfig ,
 }) {
+  final multisigConfigPointer = decodeMultisigConfig(multisigConfig: multisigConfig);
   final uint8Pointer = _bindings.multisig_salt(multisigConfigPointer);
   final bytes = uint8Pointer.asTypedList(SALT_BYTES_LENGTH);
 

From 468a724c706a37cb58920b235eb9b6c6fe62a36b Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Aug 2023 14:32:46 -0600
Subject: [PATCH 35/49] ensure free called on owned string

---
 lib/frostdart.dart | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index b4d9d0f..40062f1 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -75,9 +75,10 @@ String multisigParticipant({
 }
 
 Uint8List multisigSalt({
-  required String multisigConfig ,
+  required String multisigConfig,
 }) {
-  final multisigConfigPointer = decodeMultisigConfig(multisigConfig: multisigConfig);
+  final multisigConfigPointer =
+      decodeMultisigConfig(multisigConfig: multisigConfig);
   final uint8Pointer = _bindings.multisig_salt(multisigConfigPointer);
   final bytes = uint8Pointer.asTypedList(SALT_BYTES_LENGTH);
 
@@ -274,7 +275,7 @@ String serializeKeys({
 
   final string = ownedString.toDartString();
 
-  _bindings.free_owned_string(ownedString);
+  freeOwnedString(ownedString);
 
   return string;
 }
@@ -365,7 +366,11 @@ String addressForKeys({
 }) {
   final ownedString = _bindings.address_for_keys(network, keys);
 
-  return ownedString.toDartString();
+  final string = ownedString.toDartString();
+
+  freeOwnedString(ownedString);
+
+  return string;
 }
 
 String scriptPubKeyForKeys({
@@ -373,7 +378,11 @@ String scriptPubKeyForKeys({
 }) {
   final ownedString = _bindings.script_pub_key_for_keys(keys);
 
-  return ownedString.toDartString();
+  final string = ownedString.toDartString();
+
+  freeOwnedString(ownedString);
+
+  return string;
 }
 
 int signPaymentAmount({
@@ -575,7 +584,7 @@ String completeSign({
 
     final string = ownedString.toDartString();
 
-    _bindings.free_owned_string(ownedString);
+    freeOwnedString(ownedString);
 
     return string;
   }

From 1786222c3af3892daf36a116eaeca3705381a664 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Aug 2023 15:22:11 -0600
Subject: [PATCH 36/49] bad free

---
 lib/frostdart.dart | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 40062f1..d5b5f31 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -82,8 +82,6 @@ Uint8List multisigSalt({
   final uint8Pointer = _bindings.multisig_salt(multisigConfigPointer);
   final bytes = uint8Pointer.asTypedList(SALT_BYTES_LENGTH);
 
-  calloc.free(uint8Pointer);
-
   return bytes;
 }
 

From 41526eb903e33fa002077e9951b92964cb6c4413 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Aug 2023 09:01:18 -0600
Subject: [PATCH 37/49] make frost API more dart friendly and call appropriate
 frees

---
 example/lib/frost_sample_run.dart |  25 +++----
 lib/frostdart.dart                | 105 +++++++++++++++++-------------
 2 files changed, 66 insertions(+), 64 deletions(-)

diff --git a/example/lib/frost_sample_run.dart b/example/lib/frost_sample_run.dart
index 8399772..d68530f 100644
--- a/example/lib/frost_sample_run.dart
+++ b/example/lib/frost_sample_run.dart
@@ -33,7 +33,7 @@ abstract class FrostSampleRunner {
 
       debugPrint("Address: $address");
 
-      final signConfigRes = newSignConfig(
+      final encodedConfig = newSignConfig(
         network: network,
         outputs: [
           Output(
@@ -59,24 +59,17 @@ abstract class FrostSampleRunner {
         feePerWeight: 3000,
       );
 
-      debugPrint("created sign config (ptr address = ${signConfigRes.address}");
-
-      final String encodedConfig = signConfigRes.ref.encoded.toDartString();
-
-      final signConfig = decodeSignConfig(
-        network: network,
-        encodedSignConfig: encodedConfig,
-      );
-
       debugPrint("decoded config finished");
 
       final attemptSignResAlice = attemptSign(
         thresholdKeysWrapperPointer: deserializedKeysAlice,
-        signConfigPointer: signConfigRes.ref.config,
+        signConfig: encodedConfig,
+        network: network,
       );
       final attemptSignResBob = attemptSign(
         thresholdKeysWrapperPointer: deserializedKeysBob,
-        signConfigPointer: signConfig,
+        signConfig: encodedConfig,
+        network: network,
       );
       debugPrint("attemptSign finished");
 
@@ -147,22 +140,20 @@ abstract class FrostSampleRunner {
         "alice",
         "bob",
       ];
-      final sharedMultisigConfig = newMultisigConfig(
+      final encodedConfig = newMultisigConfig(
         name: "alice",
         threshold: 1,
         participants: participants,
       );
 
-      final encodedConfig = sharedMultisigConfig.ref.encoded.toDartString();
-
       final startGenAlice = startKeyGen(
-        multisigConfig: decodeMultisigConfig(multisigConfig: encodedConfig),
+        multisigConfig: encodedConfig,
         myName: "alice",
         language: Language.english,
       );
 
       final startGenBob = startKeyGen(
-        multisigConfig: decodeMultisigConfig(multisigConfig: encodedConfig),
+        multisigConfig: encodedConfig,
         myName: "bob",
         language: Language.english,
       );
diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index d5b5f31..de16f66 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -35,8 +35,10 @@ void freeOwnedString(OwnedString ownedString) {
 }
 
 String multisigName({
-  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+  required String multisigConfig,
 }) {
+  final multisigConfigPointer =
+      decodeMultisigConfig(multisigConfig: multisigConfig);
   final result = _bindings.multisig_name(multisigConfigPointer);
 
   final bytes = result.ptr.asTypedList(result.len);
@@ -46,21 +48,27 @@ String multisigName({
 }
 
 int multisigThreshold({
-  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+  required String multisigConfig,
 }) {
+  final multisigConfigPointer =
+      decodeMultisigConfig(multisigConfig: multisigConfig);
   return _bindings.multisig_threshold(multisigConfigPointer);
 }
 
 int multisigParticipants({
-  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+  required String multisigConfig,
 }) {
+  final multisigConfigPointer =
+      decodeMultisigConfig(multisigConfig: multisigConfig);
   return _bindings.multisig_participants(multisigConfigPointer);
 }
 
 String multisigParticipant({
-  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
   required int index,
+  required String multisigConfig,
 }) {
+  final multisigConfigPointer =
+      decodeMultisigConfig(multisigConfig: multisigConfig);
   final stringView = _bindings.multisig_participant(
     multisigConfigPointer,
     index,
@@ -106,7 +114,7 @@ String multisigMyName({
   return string;
 }
 
-ffi.Pointer<MultisigConfigRes> newMultisigConfig({
+String newMultisigConfig({
   required String name,
   required int threshold,
   required List<String> participants,
@@ -118,14 +126,6 @@ ffi.Pointer<MultisigConfigRes> newMultisigConfig({
   );
 
   for (int i = 0; i < participants.length; i++) {
-    // TODO: is this needed?
-    // final participant = participants[i];
-    // final stringViewPointer = calloc<StringView>();
-    // stringViewPointer.ref.ptr = participant.toNativeUtf8().cast<ffi.Uint8>();
-    // stringViewPointer.ref.len = participant.length;
-    // participantsPointer[i] = stringViewPointer.ref;
-
-    // TODO: or does this suffice?
     participantsPointer[i].len = participants[i].length;
     participantsPointer[i].ptr =
         participants[i].toNativeUtf8().cast<ffi.Uint8>();
@@ -145,7 +145,9 @@ ffi.Pointer<MultisigConfigRes> newMultisigConfig({
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    return result.value;
+    final string = result.value.ref.encoded.toDartString();
+    freeOwnedString(result.value.ref.encoded);
+    return string;
   }
 }
 
@@ -169,7 +171,7 @@ ffi.Pointer<MultisigConfig> decodeMultisigConfig({
 }
 
 ffi.Pointer<StartKeyGenRes> startKeyGen({
-  required ffi.Pointer<MultisigConfig> multisigConfig,
+  required String multisigConfig,
   required String myName,
   required Language language,
 }) {
@@ -177,8 +179,11 @@ ffi.Pointer<StartKeyGenRes> startKeyGen({
   stringViewPointer.ref.ptr = myName.toNativeUtf8().cast<ffi.Uint8>();
   stringViewPointer.ref.len = myName.length;
 
+  final multisigConfigPointer =
+      decodeMultisigConfig(multisigConfig: multisigConfig);
+
   final result = _bindings.start_key_gen(
-    multisigConfig,
+    multisigConfigPointer,
     stringViewPointer.ref,
     language.code,
   );
@@ -270,11 +275,8 @@ String serializeKeys({
   required ffi.Pointer<ThresholdKeysWrapper> keys,
 }) {
   final ownedString = _bindings.serialize_keys(keys);
-
   final string = ownedString.toDartString();
-
   freeOwnedString(ownedString);
-
   return string;
 }
 
@@ -296,9 +298,24 @@ ffi.Pointer<ThresholdKeysWrapper> deserializeKeys({
   }
 }
 
-Output convertOutput({
-  required ffi.Pointer<OwnedPortableOutput> ownedPortableOutputPointer,
+int signInputs({
+  required ffi.Pointer<SignConfig> signConfigPointer,
+}) {
+  return _bindings.sign_inputs(signConfigPointer);
+}
+
+Output signInput({
+  required String signConfig,
+  required int network,
+  required int index,
 }) {
+  final signConfigPointer = decodeSignConfig(
+    network: network,
+    encodedSignConfig: signConfig,
+  );
+  final ownedPortableOutputPointer =
+      _bindings.sign_input(signConfigPointer, index).value;
+
   final hashPointer = _bindings.output_hash(ownedPortableOutputPointer);
   final hash = hashPointer.asTypedList(HASH_BYTES_LENGTH);
   calloc.free(hashPointer);
@@ -322,19 +339,6 @@ Output convertOutput({
   );
 }
 
-int signInputs({
-  required ffi.Pointer<SignConfig> signConfigPointer,
-}) {
-  return _bindings.sign_inputs(signConfigPointer);
-}
-
-ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> signInput({
-  required ffi.Pointer<SignConfig> signConfigPointer,
-  required int index,
-}) {
-  return _bindings.sign_input(signConfigPointer, index);
-}
-
 int signPayments({
   required ffi.Pointer<SignConfig> signConfigPointer,
 }) {
@@ -363,11 +367,8 @@ String addressForKeys({
   required ffi.Pointer<ThresholdKeysWrapper> keys,
 }) {
   final ownedString = _bindings.address_for_keys(network, keys);
-
   final string = ownedString.toDartString();
-
   freeOwnedString(ownedString);
-
   return string;
 }
 
@@ -375,11 +376,8 @@ String scriptPubKeyForKeys({
   required ffi.Pointer<ThresholdKeysWrapper> keys,
 }) {
   final ownedString = _bindings.script_pub_key_for_keys(keys);
-
   final string = ownedString.toDartString();
-
   freeOwnedString(ownedString);
-
   return string;
 }
 
@@ -411,7 +409,7 @@ int signFeePerWeight({
   return _bindings.sign_fee_per_weight(signConfigPointer);
 }
 
-ffi.Pointer<SignConfigRes> newSignConfig({
+String newSignConfig({
   required int network,
   required List<Output> outputs,
   required List<String> paymentAddresses,
@@ -475,12 +473,22 @@ ffi.Pointer<SignConfigRes> newSignConfig({
     feePerWeight,
   );
 
-  // TODO: frees
+  for (int i = 0; i < outputs.length; i++) {
+    calloc.free(outputsPointer[i].script_pubkey);
+  }
+  calloc.free(outputsPointer);
+
+  calloc.free(paymentAddressesPointer);
+  calloc.free(paymentAmountsPointer);
+  calloc.free(stringViewPointer.ref.ptr);
+  calloc.free(stringViewPointer);
 
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    return result.value;
+    final string = result.value.ref.encoded.toDartString();
+    freeOwnedString(result.value.ref.encoded);
+    return string;
   }
 }
 
@@ -501,6 +509,7 @@ ffi.Pointer<SignConfig> decodeSignConfig({
     stringViewPointer.ref,
   );
 
+  calloc.free(stringViewPointer.ref.ptr);
   calloc.free(stringViewPointer);
 
   if (result.err != SUCCESS) {
@@ -512,8 +521,13 @@ ffi.Pointer<SignConfig> decodeSignConfig({
 
 ffi.Pointer<AttemptSignRes> attemptSign({
   required ffi.Pointer<ThresholdKeysWrapper> thresholdKeysWrapperPointer,
-  required ffi.Pointer<SignConfig> signConfigPointer,
+  required String signConfig,
+  required int network,
 }) {
+  final signConfigPointer = decodeSignConfig(
+    network: network,
+    encodedSignConfig: signConfig,
+  );
   final result = _bindings.attempt_sign(
     thresholdKeysWrapperPointer,
     signConfigPointer,
@@ -579,11 +593,8 @@ String completeSign({
     throw FrostdartException(errorCode: result.err);
   } else {
     final ownedString = result.value.ref;
-
     final string = ownedString.toDartString();
-
     freeOwnedString(ownedString);
-
     return string;
   }
 }

From 0958db58312f70d8a419601f23bcbacd28c98e9a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Aug 2023 08:27:52 -0600
Subject: [PATCH 38/49] update serai ref

---
 src/serai | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serai b/src/serai
index facbd19..011c113 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit facbd19bc1ebd3b547afaef972b194f153121191
+Subproject commit 011c11358abf3b6033a7ae99896d3ce6644ce434

From 3994ed188ce08a255c817de32aabeed05d6dd816 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Aug 2023 08:33:31 -0600
Subject: [PATCH 39/49] update bindings

---
 ffigen.yaml                           |  2 +-
 lib/frostdart.dart                    |  2 +-
 lib/frostdart_bindings_generated.dart | 12 ++++++------
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/ffigen.yaml b/ffigen.yaml
index 27f6d9f..8b88b22 100644
--- a/ffigen.yaml
+++ b/ffigen.yaml
@@ -1,7 +1,7 @@
 # Run with `flutter pub run ffigen --config ffigen.yaml`.
 name: FrostdartBindings
 description: |
-  Bindings for `src/frostdart.h`.
+  Bindings for `src/serai/hrf/header.h`.
 
   Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
 output: 'lib/frostdart_bindings_generated.dart'
diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index de16f66..1275a8a 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -375,7 +375,7 @@ String addressForKeys({
 String scriptPubKeyForKeys({
   required ffi.Pointer<ThresholdKeysWrapper> keys,
 }) {
-  final ownedString = _bindings.script_pub_key_for_keys(keys);
+  final ownedString = _bindings.script_pubkey_for_keys(keys);
   final string = ownedString.toDartString();
   freeOwnedString(ownedString);
   return string;
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 18f66ad..b90fa3b 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -8,7 +8,7 @@
 // ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
-/// Bindings for `src/frostdart.h`.
+/// Bindings for `src/serai/hrf/header.h`.
 ///
 /// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
 ///
@@ -317,19 +317,19 @@ class FrostdartBindings {
   late final _address_for_keys = _address_for_keysPtr.asFunction<
       OwnedString Function(int, ffi.Pointer<ThresholdKeysWrapper>)>();
 
-  OwnedString script_pub_key_for_keys(
+  OwnedString script_pubkey_for_keys(
     ffi.Pointer<ThresholdKeysWrapper> keys,
   ) {
-    return _script_pub_key_for_keys(
+    return _script_pubkey_for_keys(
       keys,
     );
   }
 
-  late final _script_pub_key_for_keysPtr = _lookup<
+  late final _script_pubkey_for_keysPtr = _lookup<
       ffi.NativeFunction<
           OwnedString Function(
-              ffi.Pointer<ThresholdKeysWrapper>)>>('script_pub_key_for_keys');
-  late final _script_pub_key_for_keys = _script_pub_key_for_keysPtr
+              ffi.Pointer<ThresholdKeysWrapper>)>>('script_pubkey_for_keys');
+  late final _script_pubkey_for_keys = _script_pubkey_for_keysPtr
       .asFunction<OwnedString Function(ffi.Pointer<ThresholdKeysWrapper>)>();
 
   ffi.Pointer<ffi.Uint8> output_hash(

From dcb19e1654b13a9092455cbba5078f08f9a3424e Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Aug 2023 11:28:31 -0600
Subject: [PATCH 40/49] fix memory issues

---
 lib/frostdart.dart                    | 5 +----
 lib/frostdart_bindings_generated.dart | 6 +++---
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 1275a8a..dc3a81f 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -28,7 +28,6 @@ final FrostdartBindings _bindings = FrostdartBindings(_dylib);
 
 // =============================================================================
 // ===== wrapped functions to make them as close to pure dart as possible ======
-//TODO: check missing frees
 
 void freeOwnedString(OwnedString ownedString) {
   return _bindings.free_owned_string(ownedString);
@@ -314,11 +313,10 @@ Output signInput({
     encodedSignConfig: signConfig,
   );
   final ownedPortableOutputPointer =
-      _bindings.sign_input(signConfigPointer, index).value;
+      _bindings.sign_input(signConfigPointer, index);
 
   final hashPointer = _bindings.output_hash(ownedPortableOutputPointer);
   final hash = hashPointer.asTypedList(HASH_BYTES_LENGTH);
-  calloc.free(hashPointer);
 
   final vout = _bindings.output_vout(ownedPortableOutputPointer);
 
@@ -329,7 +327,6 @@ Output signInput({
 
   final scriptPubKeyPointer = _bindings.output_hash(ownedPortableOutputPointer);
   final scriptPubKey = scriptPubKeyPointer.asTypedList(scriptPubKeyLength);
-  calloc.free(scriptPubKeyPointer);
 
   return Output(
     hash: hash,
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index b90fa3b..5738ac5 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -421,7 +421,7 @@ class FrostdartBindings {
   late final _sign_inputs =
       _sign_inputsPtr.asFunction<int Function(ffi.Pointer<SignConfig>)>();
 
-  ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> sign_input(
+  ffi.Pointer<OwnedPortableOutput> sign_input(
     ffi.Pointer<SignConfig> self,
     int i,
   ) {
@@ -433,10 +433,10 @@ class FrostdartBindings {
 
   late final _sign_inputPtr = _lookup<
       ffi.NativeFunction<
-          ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> Function(
+          ffi.Pointer<OwnedPortableOutput> Function(
               ffi.Pointer<SignConfig>, ffi.UintPtr)>>('sign_input');
   late final _sign_input = _sign_inputPtr.asFunction<
-      ffi.Pointer<ffi.Pointer<OwnedPortableOutput>> Function(
+      ffi.Pointer<OwnedPortableOutput> Function(
           ffi.Pointer<SignConfig>, int)>();
 
   int sign_payments(

From d806b6146f24931c685e184b27b5b7b7c792ab2c Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 23 Aug 2023 09:55:17 -0600
Subject: [PATCH 41/49] update serai ref

---
 src/serai | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serai b/src/serai
index 011c113..2d23ad4 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 011c11358abf3b6033a7ae99896d3ce6644ce434
+Subproject commit 2d23ad42364281ee5826dee98639127da615e599

From 6efbe4944c7f6736c62602ce1fc17dcb5f99ac4b Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 23 Aug 2023 09:55:46 -0600
Subject: [PATCH 42/49] add wrapper calls for getting participant info from
 serialized keys

---
 lib/frostdart.dart                    | 15 +++++++++
 lib/frostdart_bindings_generated.dart | 45 +++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index dc3a81f..46922ad 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -270,6 +270,21 @@ ffi.Pointer<KeyGenRes> completeKeyGen({
   }
 }
 
+int getThresholdFromKeys({required String serializedKeys}) {
+  final keysPointer = deserializeKeys(keys: serializedKeys);
+  return _bindings.keys_threshold(keysPointer);
+}
+
+int getParticipantsCountFromKeys({required String serializedKeys}) {
+  final keysPointer = deserializeKeys(keys: serializedKeys);
+  return _bindings.keys_participants(keysPointer);
+}
+
+int getParticipantIndexFromKeys({required String serializedKeys}) {
+  final keysPointer = deserializeKeys(keys: serializedKeys);
+  return _bindings.keys_index(keysPointer);
+}
+
 String serializeKeys({
   required ffi.Pointer<ThresholdKeysWrapper> keys,
 }) {
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 5738ac5..8aed010 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -270,6 +270,51 @@ class FrostdartBindings {
       CResult_KeyGenRes Function(ffi.Pointer<MultisigConfigWithName>,
           SecretSharesRes, ffi.Pointer<StringView>, int)>();
 
+  int keys_threshold(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+  ) {
+    return _keys_threshold(
+      keys,
+    );
+  }
+
+  late final _keys_thresholdPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint16 Function(
+              ffi.Pointer<ThresholdKeysWrapper>)>>('keys_threshold');
+  late final _keys_threshold = _keys_thresholdPtr
+      .asFunction<int Function(ffi.Pointer<ThresholdKeysWrapper>)>();
+
+  int keys_participants(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+  ) {
+    return _keys_participants(
+      keys,
+    );
+  }
+
+  late final _keys_participantsPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint16 Function(
+              ffi.Pointer<ThresholdKeysWrapper>)>>('keys_participants');
+  late final _keys_participants = _keys_participantsPtr
+      .asFunction<int Function(ffi.Pointer<ThresholdKeysWrapper>)>();
+
+  int keys_index(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+  ) {
+    return _keys_index(
+      keys,
+    );
+  }
+
+  late final _keys_indexPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint16 Function(
+              ffi.Pointer<ThresholdKeysWrapper>)>>('keys_index');
+  late final _keys_index = _keys_indexPtr
+      .asFunction<int Function(ffi.Pointer<ThresholdKeysWrapper>)>();
+
   OwnedString serialize_keys(
     ffi.Pointer<ThresholdKeysWrapper> keys,
   ) {

From ffa6952e4f9045d5409b14fd75ccefaa38046115 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 24 Aug 2023 08:21:18 -0600
Subject: [PATCH 43/49] WIP resharing bindings

---
 lib/frostdart.dart                    | 221 ++++++++++++++++++++++
 lib/frostdart_bindings_generated.dart | 260 ++++++++++++++++++++++++++
 src/serai                             |   2 +-
 3 files changed, 482 insertions(+), 1 deletion(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 46922ad..21ef0a6 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -610,3 +610,224 @@ String completeSign({
     return string;
   }
 }
+
+int resharerNewThreshold({
+  required ffi.Pointer<ResharerConfig> resharerConfigPointer,
+}) {
+  return _bindings.resharer_new_threshold(resharerConfigPointer);
+}
+
+int resharerResharers({
+  required ffi.Pointer<ResharerConfig> resharerConfigPointer,
+}) {
+  return _bindings.resharer_resharers(resharerConfigPointer);
+}
+
+// TODO: should return a string?
+int resharerResharer({
+  required ffi.Pointer<ResharerConfig> resharerConfigPointer,
+  required int index,
+}) {
+  return _bindings.resharer_resharer(resharerConfigPointer, index);
+}
+
+int resharerNewParticipants({
+  required ffi.Pointer<ResharerConfig> resharerConfigPointer,
+}) {
+  return _bindings.resharer_new_participants(resharerConfigPointer);
+}
+
+String resharerNewParticipant({
+  required ffi.Pointer<ResharerConfig> resharerConfigPointer,
+  required int index,
+}) {
+  final stringView =
+      _bindings.resharer_new_participant(resharerConfigPointer, index);
+
+  final utf8Pointer = stringView.ptr.cast<Utf8>();
+  final string = utf8Pointer.toDartString(length: stringView.len);
+
+  calloc.free(utf8Pointer);
+
+  return string;
+}
+
+String newResharerConfig({
+  required int newThreshold,
+  required List<int> resharers,
+  required List<String> newParticipants,
+}) {
+  ffi.Pointer<ffi.Uint16> resharersPointer =
+      calloc<ffi.Uint16>(resharers.length);
+
+  for (int i = 0; i < resharers.length; i++) {
+    resharersPointer[i] = resharers[i];
+  }
+
+  ffi.Pointer<StringView> newParticipantsPointer = calloc<StringView>(
+    newParticipants.length,
+  );
+
+  for (int i = 0; i < newParticipants.length; i++) {
+    newParticipantsPointer[i].len = newParticipants[i].length;
+    newParticipantsPointer[i].ptr =
+        newParticipants[i].toNativeUtf8().cast<ffi.Uint8>();
+  }
+
+  final result = _bindings.new_resharer_config(
+    newThreshold,
+    resharersPointer,
+    resharers.length,
+    newParticipantsPointer,
+    newParticipants.length,
+  );
+
+  calloc.free(resharersPointer);
+  calloc.free(newParticipantsPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    final string = result.value.ref.encoded.toDartString();
+    freeOwnedString(result.value.ref.encoded);
+    return string;
+  }
+}
+
+ffi.Pointer<ResharerConfig> decodeResharerConfig({
+  required String resharerConfig,
+}) {
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = resharerConfig.toNativeUtf8().cast<ffi.Uint8>();
+  stringViewPointer.ref.len = resharerConfig.length;
+
+  final result = _bindings.decode_resharer_config(stringViewPointer.ref);
+
+  calloc.free(stringViewPointer.ref.ptr);
+  calloc.free(stringViewPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    // TODO fix Pointer<Pointer<>>
+    return result.value.value;
+  }
+}
+
+// TODO change return value?
+ffi.Pointer<StartResharerRes> startResharer({
+  required String serializedKeys,
+  required String config,
+}) {
+  final configPointer = decodeResharerConfig(resharerConfig: config);
+  final keysPointer = deserializeKeys(keys: serializedKeys);
+
+  final result = _bindings.start_resharer(keysPointer, configPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    // final string = result.value.ref.encoded.toDartString();
+    // freeOwnedString(result.value.ref.encoded);
+    // return string;
+    return result.value;
+  }
+}
+
+// TODO change return value?
+ffi.Pointer<StartResharedRes> startReshared({
+  required String multisigConfig,
+  required String resharerConfig,
+  required List<String> resharerStarts,
+}) {
+  final multisigConfigPointer = decodeMultisigConfig(
+    multisigConfig: multisigConfig,
+  );
+  final resharerConfigPointer = decodeResharerConfig(
+    resharerConfig: resharerConfig,
+  );
+
+  ffi.Pointer<StringView> resharerStartsPointer = calloc<StringView>(
+    resharerStarts.length,
+  );
+  for (int i = 0; i < resharerStarts.length; i++) {
+    resharerStartsPointer[i].len = resharerStarts[i].length;
+    resharerStartsPointer[i].ptr =
+        resharerStarts[i].toNativeUtf8().cast<ffi.Uint8>();
+  }
+
+  final result = _bindings.start_reshared(
+    multisigConfigPointer,
+    resharerConfigPointer,
+    resharerStartsPointer,
+  );
+
+  calloc.free(resharerStartsPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    // final string = result.value.ref.encoded.toDartString();
+    // freeOwnedString(result.value.ref.encoded);
+    // return string;
+    return result.value;
+  }
+}
+
+// TODO change return value
+CResult_CompleteResharerRes completeResharer({
+  required StartResharerRes machine,
+  required List<String> encryptionKeysOfResharedTo,
+}) {
+  ffi.Pointer<StringView> encryptionKeysOfResharedToPointer =
+      calloc<StringView>(
+    encryptionKeysOfResharedTo.length,
+  );
+  for (int i = 0; i < encryptionKeysOfResharedTo.length; i++) {
+    encryptionKeysOfResharedToPointer[i].len =
+        encryptionKeysOfResharedTo[i].length;
+    encryptionKeysOfResharedToPointer[i].ptr =
+        encryptionKeysOfResharedTo[i].toNativeUtf8().cast<ffi.Uint8>();
+  }
+
+  final result = _bindings.complete_resharer(
+    machine,
+    encryptionKeysOfResharedToPointer,
+  );
+
+  calloc.free(encryptionKeysOfResharedToPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result;
+  }
+}
+
+// TODO change return value
+CResult_CompleteResharedRes completeReshared({
+  required StartResharedRes machine,
+  required List<String> resharerCompletes,
+}) {
+  ffi.Pointer<StringView> resharerCompletesPointer = calloc<StringView>(
+    resharerCompletes.length,
+  );
+  for (int i = 0; i < resharerCompletes.length; i++) {
+    resharerCompletesPointer[i].len = resharerCompletes[i].length;
+    resharerCompletesPointer[i].ptr =
+        resharerCompletes[i].toNativeUtf8().cast<ffi.Uint8>();
+  }
+
+  final result = _bindings.complete_reshared(
+    machine,
+    resharerCompletesPointer,
+  );
+
+  calloc.free(resharerCompletesPointer);
+
+  if (result.err != SUCCESS) {
+    throw FrostdartException(errorCode: result.err);
+  } else {
+    return result;
+  }
+}
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 8aed010..5169d51 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -679,6 +679,202 @@ class FrostdartBindings {
           ffi.Pointer<TransactionSignatureMachineWrapper>,
           ffi.Pointer<StringView>,
           int)>();
+
+  int resharer_new_threshold(
+    ffi.Pointer<ResharerConfig> self,
+  ) {
+    return _resharer_new_threshold(
+      self,
+    );
+  }
+
+  late final _resharer_new_thresholdPtr = _lookup<
+          ffi.NativeFunction<ffi.Uint16 Function(ffi.Pointer<ResharerConfig>)>>(
+      'resharer_new_threshold');
+  late final _resharer_new_threshold = _resharer_new_thresholdPtr
+      .asFunction<int Function(ffi.Pointer<ResharerConfig>)>();
+
+  int resharer_resharers(
+    ffi.Pointer<ResharerConfig> self,
+  ) {
+    return _resharer_resharers(
+      self,
+    );
+  }
+
+  late final _resharer_resharersPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.UintPtr Function(
+              ffi.Pointer<ResharerConfig>)>>('resharer_resharers');
+  late final _resharer_resharers = _resharer_resharersPtr
+      .asFunction<int Function(ffi.Pointer<ResharerConfig>)>();
+
+  int resharer_resharer(
+    ffi.Pointer<ResharerConfig> self,
+    int i,
+  ) {
+    return _resharer_resharer(
+      self,
+      i,
+    );
+  }
+
+  late final _resharer_resharerPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint16 Function(
+              ffi.Pointer<ResharerConfig>, ffi.UintPtr)>>('resharer_resharer');
+  late final _resharer_resharer = _resharer_resharerPtr
+      .asFunction<int Function(ffi.Pointer<ResharerConfig>, int)>();
+
+  int resharer_new_participants(
+    ffi.Pointer<ResharerConfig> self,
+  ) {
+    return _resharer_new_participants(
+      self,
+    );
+  }
+
+  late final _resharer_new_participantsPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.UintPtr Function(
+              ffi.Pointer<ResharerConfig>)>>('resharer_new_participants');
+  late final _resharer_new_participants = _resharer_new_participantsPtr
+      .asFunction<int Function(ffi.Pointer<ResharerConfig>)>();
+
+  StringView resharer_new_participant(
+    ffi.Pointer<ResharerConfig> self,
+    int i,
+  ) {
+    return _resharer_new_participant(
+      self,
+      i,
+    );
+  }
+
+  late final _resharer_new_participantPtr = _lookup<
+      ffi.NativeFunction<
+          StringView Function(ffi.Pointer<ResharerConfig>,
+              ffi.UintPtr)>>('resharer_new_participant');
+  late final _resharer_new_participant = _resharer_new_participantPtr
+      .asFunction<StringView Function(ffi.Pointer<ResharerConfig>, int)>();
+
+  CResult_ResharerConfigRes new_resharer_config(
+    int new_threshold,
+    ffi.Pointer<ffi.Uint16> resharers,
+    int resharers_len,
+    ffi.Pointer<StringView> new_participants,
+    int new_participants_len,
+  ) {
+    return _new_resharer_config(
+      new_threshold,
+      resharers,
+      resharers_len,
+      new_participants,
+      new_participants_len,
+    );
+  }
+
+  late final _new_resharer_configPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_ResharerConfigRes Function(
+              ffi.Uint16,
+              ffi.Pointer<ffi.Uint16>,
+              ffi.Uint16,
+              ffi.Pointer<StringView>,
+              ffi.Uint16)>>('new_resharer_config');
+  late final _new_resharer_config = _new_resharer_configPtr.asFunction<
+      CResult_ResharerConfigRes Function(
+          int, ffi.Pointer<ffi.Uint16>, int, ffi.Pointer<StringView>, int)>();
+
+  CResult_____ResharerConfig decode_resharer_config(
+    StringView config,
+  ) {
+    return _decode_resharer_config(
+      config,
+    );
+  }
+
+  late final _decode_resharer_configPtr = _lookup<
+          ffi.NativeFunction<CResult_____ResharerConfig Function(StringView)>>(
+      'decode_resharer_config');
+  late final _decode_resharer_config = _decode_resharer_configPtr
+      .asFunction<CResult_____ResharerConfig Function(StringView)>();
+
+  CResult_StartResharerRes start_resharer(
+    ffi.Pointer<ThresholdKeysWrapper> keys,
+    ffi.Pointer<ResharerConfig> config,
+  ) {
+    return _start_resharer(
+      keys,
+      config,
+    );
+  }
+
+  late final _start_resharerPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_StartResharerRes Function(ffi.Pointer<ThresholdKeysWrapper>,
+              ffi.Pointer<ResharerConfig>)>>('start_resharer');
+  late final _start_resharer = _start_resharerPtr.asFunction<
+      CResult_StartResharerRes Function(
+          ffi.Pointer<ThresholdKeysWrapper>, ffi.Pointer<ResharerConfig>)>();
+
+  CResult_StartResharedRes start_reshared(
+    ffi.Pointer<MultisigConfig> multisig_config,
+    ffi.Pointer<ResharerConfig> reshared_config,
+    ffi.Pointer<StringView> resharer_starts,
+  ) {
+    return _start_reshared(
+      multisig_config,
+      reshared_config,
+      resharer_starts,
+    );
+  }
+
+  late final _start_resharedPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_StartResharedRes Function(
+              ffi.Pointer<MultisigConfig>,
+              ffi.Pointer<ResharerConfig>,
+              ffi.Pointer<StringView>)>>('start_reshared');
+  late final _start_reshared = _start_resharedPtr.asFunction<
+      CResult_StartResharedRes Function(ffi.Pointer<MultisigConfig>,
+          ffi.Pointer<ResharerConfig>, ffi.Pointer<StringView>)>();
+
+  CResult_CompleteResharerRes complete_resharer(
+    StartResharerRes machine,
+    ffi.Pointer<StringView> encryption_keys_of_reshared_to,
+  ) {
+    return _complete_resharer(
+      machine,
+      encryption_keys_of_reshared_to,
+    );
+  }
+
+  late final _complete_resharerPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_CompleteResharerRes Function(
+              StartResharerRes, ffi.Pointer<StringView>)>>('complete_resharer');
+  late final _complete_resharer = _complete_resharerPtr.asFunction<
+      CResult_CompleteResharerRes Function(
+          StartResharerRes, ffi.Pointer<StringView>)>();
+
+  CResult_CompleteResharedRes complete_reshared(
+    StartResharedRes machine,
+    ffi.Pointer<StringView> resharer_completes,
+  ) {
+    return _complete_reshared(
+      machine,
+      resharer_completes,
+    );
+  }
+
+  late final _complete_resharedPtr = _lookup<
+      ffi.NativeFunction<
+          CResult_CompleteResharedRes Function(
+              StartResharedRes, ffi.Pointer<StringView>)>>('complete_reshared');
+  late final _complete_reshared = _complete_resharedPtr.asFunction<
+      CResult_CompleteResharedRes Function(
+          StartResharedRes, ffi.Pointer<StringView>)>();
 }
 
 abstract class Network {
@@ -693,6 +889,8 @@ final class MultisigConfig extends ffi.Opaque {}
 
 final class OwnedPortableOutput extends ffi.Opaque {}
 
+final class ResharerConfig extends ffi.Opaque {}
+
 final class SecretShareMachineWrapper extends ffi.Opaque {}
 
 final class SignConfig extends ffi.Opaque {}
@@ -873,6 +1071,68 @@ final class CResult_OwnedString extends ffi.Struct {
   external int err;
 }
 
+final class ResharerConfigRes extends ffi.Struct {
+  external ffi.Pointer<ResharerConfig> config;
+
+  external OwnedString encoded;
+}
+
+final class CResult_ResharerConfigRes extends ffi.Struct {
+  external ffi.Pointer<ResharerConfigRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class CResult_____ResharerConfig extends ffi.Struct {
+  external ffi.Pointer<ffi.Pointer<ResharerConfig>> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class StartResharerRes extends ffi.Struct {
+  external OwnedString encoded;
+}
+
+final class CResult_StartResharerRes extends ffi.Struct {
+  external ffi.Pointer<StartResharerRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class StartResharedRes extends ffi.Struct {
+  external OwnedString encoded;
+}
+
+final class CResult_StartResharedRes extends ffi.Struct {
+  external ffi.Pointer<StartResharedRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class CompleteResharerRes extends ffi.Struct {
+  external OwnedString encoded;
+}
+
+final class CResult_CompleteResharerRes extends ffi.Struct {
+  external ffi.Pointer<CompleteResharerRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
+final class CompleteResharedRes extends ffi.Opaque {}
+
+final class CResult_CompleteResharedRes extends ffi.Struct {
+  external ffi.Pointer<CompleteResharedRes> value;
+
+  @ffi.Uint16()
+  external int err;
+}
+
 const int LANGUAGE_ENGLISH = 1;
 
 const int LANGUAGE_CHINESE_SIMPLIFIED = 2;
diff --git a/src/serai b/src/serai
index 2d23ad4..a1057ba 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 2d23ad42364281ee5826dee98639127da615e599
+Subproject commit a1057bae410c16ab316217df7ab656d874442db2

From 24da4fd204ab54185d521bf240d50c6aa819d2cc Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 24 Aug 2023 11:51:28 -0600
Subject: [PATCH 44/49] update resharing bindings

---
 lib/frostdart.dart                    |  55 +++++-----
 lib/frostdart_bindings_generated.dart | 141 +++++++++++++++-----------
 lib/util.dart                         |  10 ++
 src/serai                             |   2 +-
 4 files changed, 117 insertions(+), 91 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 21ef0a6..23e4fea 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -623,7 +623,6 @@ int resharerResharers({
   return _bindings.resharer_resharers(resharerConfigPointer);
 }
 
-// TODO: should return a string?
 int resharerResharer({
   required ffi.Pointer<ResharerConfig> resharerConfigPointer,
   required int index,
@@ -709,13 +708,11 @@ ffi.Pointer<ResharerConfig> decodeResharerConfig({
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    // TODO fix Pointer<Pointer<>>
-    return result.value.value;
+    return result.value;
   }
 }
 
-// TODO change return value?
-ffi.Pointer<StartResharerRes> startResharer({
+({ffi.Pointer<StartResharerRes> machine, String encoded}) startResharer({
   required String serializedKeys,
   required String config,
 }) {
@@ -727,22 +724,22 @@ ffi.Pointer<StartResharerRes> startResharer({
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    // final string = result.value.ref.encoded.toDartString();
-    // freeOwnedString(result.value.ref.encoded);
-    // return string;
-    return result.value;
+    final string = result.value.ref.encoded.toDartString();
+    freeOwnedString(result.value.ref.encoded);
+
+    return (machine: result.value, encoded: string);
   }
 }
 
-// TODO change return value?
-ffi.Pointer<StartResharedRes> startReshared({
-  required String multisigConfig,
+({ffi.Pointer<StartResharedRes> machine, String encoded}) startReshared({
   required String resharerConfig,
+  required String myName,
   required List<String> resharerStarts,
 }) {
-  final multisigConfigPointer = decodeMultisigConfig(
-    multisigConfig: multisigConfig,
-  );
+  final stringViewPointer = calloc<StringView>();
+  stringViewPointer.ref.ptr = myName.toNativeUtf8().cast<ffi.Uint8>();
+  stringViewPointer.ref.len = myName.length;
+
   final resharerConfigPointer = decodeResharerConfig(
     resharerConfig: resharerConfig,
   );
@@ -757,25 +754,26 @@ ffi.Pointer<StartResharedRes> startReshared({
   }
 
   final result = _bindings.start_reshared(
-    multisigConfigPointer,
     resharerConfigPointer,
+    stringViewPointer.ref,
     resharerStartsPointer,
   );
 
   calloc.free(resharerStartsPointer);
+  calloc.free(stringViewPointer.ref.ptr);
+  calloc.free(stringViewPointer);
 
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    // final string = result.value.ref.encoded.toDartString();
-    // freeOwnedString(result.value.ref.encoded);
-    // return string;
-    return result.value;
+    final string = result.value.ref.encoded.toDartString();
+    freeOwnedString(result.value.ref.encoded);
+
+    return (machine: result.value, encoded: string);
   }
 }
 
-// TODO change return value
-CResult_CompleteResharerRes completeResharer({
+String completeResharer({
   required StartResharerRes machine,
   required List<String> encryptionKeysOfResharedTo,
 }) {
@@ -800,13 +798,14 @@ CResult_CompleteResharerRes completeResharer({
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    return result;
+    final string = result.value.ref.toDartString();
+    freeOwnedString(result.value.ref);
+    return string;
   }
 }
 
-// TODO change return value
-CResult_CompleteResharedRes completeReshared({
-  required StartResharedRes machine,
+String completeReshared({
+  required StartResharedRes prior,
   required List<String> resharerCompletes,
 }) {
   ffi.Pointer<StringView> resharerCompletesPointer = calloc<StringView>(
@@ -819,7 +818,7 @@ CResult_CompleteResharedRes completeReshared({
   }
 
   final result = _bindings.complete_reshared(
-    machine,
+    prior,
     resharerCompletesPointer,
   );
 
@@ -828,6 +827,6 @@ CResult_CompleteResharedRes completeReshared({
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    return result;
+    return serializeKeys(keys: result.value);
   }
 }
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 5169d51..f0fc5c0 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -204,7 +204,7 @@ class FrostdartBindings {
   late final _start_key_genPtr = _lookup<
       ffi.NativeFunction<
           CResult_StartKeyGenRes Function(ffi.Pointer<MultisigConfig>,
-              StringView, ffi.Uint16)>>('start_key_gen');
+              StringView, ffi.Uint8)>>('start_key_gen');
   late final _start_key_gen = _start_key_genPtr.asFunction<
       CResult_StartKeyGenRes Function(
           ffi.Pointer<MultisigConfig>, StringView, int)>();
@@ -231,7 +231,7 @@ class FrostdartBindings {
       ffi.NativeFunction<
           CResult_SecretSharesRes Function(
               ffi.Pointer<MultisigConfigWithName>,
-              ffi.Uint16,
+              ffi.Uint8,
               StringView,
               ffi.Pointer<SecretShareMachineWrapper>,
               ffi.Pointer<StringView>,
@@ -758,6 +758,21 @@ class FrostdartBindings {
   late final _resharer_new_participant = _resharer_new_participantPtr
       .asFunction<StringView Function(ffi.Pointer<ResharerConfig>, int)>();
 
+  ffi.Pointer<ffi.Uint8> resharer_salt(
+    ffi.Pointer<ResharerConfig> self,
+  ) {
+    return _resharer_salt(
+      self,
+    );
+  }
+
+  late final _resharer_saltPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ffi.Uint8> Function(
+              ffi.Pointer<ResharerConfig>)>>('resharer_salt');
+  late final _resharer_salt = _resharer_saltPtr.asFunction<
+      ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<ResharerConfig>)>();
+
   CResult_ResharerConfigRes new_resharer_config(
     int new_threshold,
     ffi.Pointer<ffi.Uint16> resharers,
@@ -786,7 +801,7 @@ class FrostdartBindings {
       CResult_ResharerConfigRes Function(
           int, ffi.Pointer<ffi.Uint16>, int, ffi.Pointer<StringView>, int)>();
 
-  CResult_____ResharerConfig decode_resharer_config(
+  CResult_ResharerConfig decode_resharer_config(
     StringView config,
   ) {
     return _decode_resharer_config(
@@ -794,11 +809,11 @@ class FrostdartBindings {
     );
   }
 
-  late final _decode_resharer_configPtr = _lookup<
-          ffi.NativeFunction<CResult_____ResharerConfig Function(StringView)>>(
-      'decode_resharer_config');
+  late final _decode_resharer_configPtr =
+      _lookup<ffi.NativeFunction<CResult_ResharerConfig Function(StringView)>>(
+          'decode_resharer_config');
   late final _decode_resharer_config = _decode_resharer_configPtr
-      .asFunction<CResult_____ResharerConfig Function(StringView)>();
+      .asFunction<CResult_ResharerConfig Function(StringView)>();
 
   CResult_StartResharerRes start_resharer(
     ffi.Pointer<ThresholdKeysWrapper> keys,
@@ -819,28 +834,26 @@ class FrostdartBindings {
           ffi.Pointer<ThresholdKeysWrapper>, ffi.Pointer<ResharerConfig>)>();
 
   CResult_StartResharedRes start_reshared(
-    ffi.Pointer<MultisigConfig> multisig_config,
-    ffi.Pointer<ResharerConfig> reshared_config,
+    ffi.Pointer<ResharerConfig> resharer_config,
+    StringView my_name,
     ffi.Pointer<StringView> resharer_starts,
   ) {
     return _start_reshared(
-      multisig_config,
-      reshared_config,
+      resharer_config,
+      my_name,
       resharer_starts,
     );
   }
 
   late final _start_resharedPtr = _lookup<
       ffi.NativeFunction<
-          CResult_StartResharedRes Function(
-              ffi.Pointer<MultisigConfig>,
-              ffi.Pointer<ResharerConfig>,
-              ffi.Pointer<StringView>)>>('start_reshared');
+          CResult_StartResharedRes Function(ffi.Pointer<ResharerConfig>,
+              StringView, ffi.Pointer<StringView>)>>('start_reshared');
   late final _start_reshared = _start_resharedPtr.asFunction<
-      CResult_StartResharedRes Function(ffi.Pointer<MultisigConfig>,
-          ffi.Pointer<ResharerConfig>, ffi.Pointer<StringView>)>();
+      CResult_StartResharedRes Function(
+          ffi.Pointer<ResharerConfig>, StringView, ffi.Pointer<StringView>)>();
 
-  CResult_CompleteResharerRes complete_resharer(
+  CResult_OwnedString complete_resharer(
     StartResharerRes machine,
     ffi.Pointer<StringView> encryption_keys_of_reshared_to,
   ) {
@@ -852,28 +865,28 @@ class FrostdartBindings {
 
   late final _complete_resharerPtr = _lookup<
       ffi.NativeFunction<
-          CResult_CompleteResharerRes Function(
+          CResult_OwnedString Function(
               StartResharerRes, ffi.Pointer<StringView>)>>('complete_resharer');
   late final _complete_resharer = _complete_resharerPtr.asFunction<
-      CResult_CompleteResharerRes Function(
+      CResult_OwnedString Function(
           StartResharerRes, ffi.Pointer<StringView>)>();
 
-  CResult_CompleteResharedRes complete_reshared(
-    StartResharedRes machine,
+  CResult_ThresholdKeysWrapper complete_reshared(
+    StartResharedRes prior,
     ffi.Pointer<StringView> resharer_completes,
   ) {
     return _complete_reshared(
-      machine,
+      prior,
       resharer_completes,
     );
   }
 
   late final _complete_resharedPtr = _lookup<
       ffi.NativeFunction<
-          CResult_CompleteResharedRes Function(
+          CResult_ThresholdKeysWrapper Function(
               StartResharedRes, ffi.Pointer<StringView>)>>('complete_reshared');
   late final _complete_reshared = _complete_resharedPtr.asFunction<
-      CResult_CompleteResharedRes Function(
+      CResult_ThresholdKeysWrapper Function(
           StartResharedRes, ffi.Pointer<StringView>)>();
 }
 
@@ -887,6 +900,10 @@ final class KeyMachineWrapper extends ffi.Opaque {}
 
 final class MultisigConfig extends ffi.Opaque {}
 
+final class OpaqueResharedMachine extends ffi.Opaque {}
+
+final class OpaqueResharingMachine extends ffi.Opaque {}
+
 final class OwnedPortableOutput extends ffi.Opaque {}
 
 final class ResharerConfig extends ffi.Opaque {}
@@ -936,14 +953,14 @@ final class MultisigConfigRes extends ffi.Struct {
 final class CResult_MultisigConfigRes extends ffi.Struct {
   external ffi.Pointer<MultisigConfigRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
 final class CResult_MultisigConfig extends ffi.Struct {
   external ffi.Pointer<MultisigConfig> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -960,7 +977,7 @@ final class StartKeyGenRes extends ffi.Struct {
 final class CResult_StartKeyGenRes extends ffi.Struct {
   external ffi.Pointer<StartKeyGenRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -975,7 +992,7 @@ final class SecretSharesRes extends ffi.Struct {
 final class CResult_SecretSharesRes extends ffi.Struct {
   external ffi.Pointer<SecretSharesRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -991,14 +1008,14 @@ final class KeyGenRes extends ffi.Struct {
 final class CResult_KeyGenRes extends ffi.Struct {
   external ffi.Pointer<KeyGenRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
 final class CResult_ThresholdKeysWrapper extends ffi.Struct {
   external ffi.Pointer<ThresholdKeysWrapper> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -1011,7 +1028,7 @@ final class SignConfigRes extends ffi.Struct {
 final class CResult_SignConfigRes extends ffi.Struct {
   external ffi.Pointer<SignConfigRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -1034,7 +1051,7 @@ final class PortableOutput extends ffi.Struct {
 final class CResult_SignConfig extends ffi.Struct {
   external ffi.Pointer<SignConfig> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -1047,7 +1064,7 @@ final class AttemptSignRes extends ffi.Struct {
 final class CResult_AttemptSignRes extends ffi.Struct {
   external ffi.Pointer<AttemptSignRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -1060,14 +1077,14 @@ final class ContinueSignRes extends ffi.Struct {
 final class CResult_ContinueSignRes extends ffi.Struct {
   external ffi.Pointer<ContinueSignRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
 final class CResult_OwnedString extends ffi.Struct {
   external ffi.Pointer<OwnedString> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -1080,56 +1097,46 @@ final class ResharerConfigRes extends ffi.Struct {
 final class CResult_ResharerConfigRes extends ffi.Struct {
   external ffi.Pointer<ResharerConfigRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
-final class CResult_____ResharerConfig extends ffi.Struct {
-  external ffi.Pointer<ffi.Pointer<ResharerConfig>> value;
+final class CResult_ResharerConfig extends ffi.Struct {
+  external ffi.Pointer<ResharerConfig> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
 final class StartResharerRes extends ffi.Struct {
+  @ffi.UintPtr()
+  external int new_participants_len;
+
+  external ffi.Pointer<OpaqueResharingMachine> machine;
+
   external OwnedString encoded;
 }
 
 final class CResult_StartResharerRes extends ffi.Struct {
   external ffi.Pointer<StartResharerRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
 final class StartResharedRes extends ffi.Struct {
-  external OwnedString encoded;
-}
-
-final class CResult_StartResharedRes extends ffi.Struct {
-  external ffi.Pointer<StartResharedRes> value;
+  @ffi.UintPtr()
+  external int resharers_len;
 
-  @ffi.Uint16()
-  external int err;
-}
+  external ffi.Pointer<OpaqueResharedMachine> machine;
 
-final class CompleteResharerRes extends ffi.Struct {
   external OwnedString encoded;
 }
 
-final class CResult_CompleteResharerRes extends ffi.Struct {
-  external ffi.Pointer<CompleteResharerRes> value;
-
-  @ffi.Uint16()
-  external int err;
-}
-
-final class CompleteResharedRes extends ffi.Opaque {}
-
-final class CResult_CompleteResharedRes extends ffi.Struct {
-  external ffi.Pointer<CompleteResharedRes> value;
+final class CResult_StartResharedRes extends ffi.Struct {
+  external ffi.Pointer<StartResharedRes> value;
 
-  @ffi.Uint16()
+  @ffi.Uint8()
   external int err;
 }
 
@@ -1192,3 +1199,13 @@ const int TOO_LARGE_TRANSACTION_ERROR = 68;
 const int WRONG_KEYS_ERROR = 69;
 
 const int INVALID_PREPROCESS_ERROR = 70;
+
+const int INVALID_PARTICIPANTS_AMOUNT_ERROR = 81;
+
+const int DUPLICATED_PARTICIPANT_ERROR = 82;
+
+const int NOT_ENOUGH_RESHARERS_ERROR = 83;
+
+const int INVALID_RESHARED_MSG_ERROR = 84;
+
+const int INVALID_RESHARER_MSG_ERROR = 85;
diff --git a/lib/util.dart b/lib/util.dart
index 695aef6..d4c630a 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -79,6 +79,16 @@ String getErrorName(int errorCode) {
       return 'WRONG_KEYS_ERROR';
     case INVALID_PREPROCESS_ERROR:
       return 'INVALID_PREPROCESS_ERROR';
+    case INVALID_PARTICIPANTS_AMOUNT_ERROR:
+      return 'INVALID_PARTICIPANTS_AMOUNT_ERROR';
+    case DUPLICATED_PARTICIPANT_ERROR:
+      return 'DUPLICATED_PARTICIPANT_ERROR';
+    case NOT_ENOUGH_RESHARERS_ERROR:
+      return 'NOT_ENOUGH_RESHARERS_ERROR';
+    case INVALID_RESHARED_MSG_ERROR:
+      return 'INVALID_RESHARED_MSG_ERROR';
+    case INVALID_RESHARER_MSG_ERROR:
+      return 'INVALID_RESHARER_MSG_ERROR';
     default:
       return 'UNKNOWN ERROR CODE "$errorCode"';
   }
diff --git a/src/serai b/src/serai
index a1057ba..84ec308 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit a1057bae410c16ab316217df7ab656d874442db2
+Subproject commit 84ec308624b8fb21c0e4c25b7906fc35abc6cf56

From 6eb209fb63d58a596f5b497565c23c391133ae9f Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 25 Aug 2023 15:59:19 -0600
Subject: [PATCH 45/49] updates and fixes for resharing

---
 lib/frostdart.dart                    | 49 +++++++++++---
 lib/frostdart_bindings_generated.dart | 95 +++++++++++++++++++--------
 lib/util.dart                         |  2 +
 src/serai                             |  2 +-
 4 files changed, 111 insertions(+), 37 deletions(-)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index 23e4fea..e3df752 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -169,6 +169,16 @@ ffi.Pointer<MultisigConfig> decodeMultisigConfig({
   }
 }
 
+String encodeMultisigConfig({
+  required ffi.Pointer<MultisigConfig> multisigConfigPointer,
+}) {
+  final ownedString = _bindings.encode_multisig_config(multisigConfigPointer);
+  final encoded = ownedString.toDartString();
+  freeOwnedString(ownedString);
+
+  return encoded;
+}
+
 ffi.Pointer<StartKeyGenRes> startKeyGen({
   required String multisigConfig,
   required String myName,
@@ -731,14 +741,20 @@ ffi.Pointer<ResharerConfig> decodeResharerConfig({
   }
 }
 
+/// [newMultisigName] doesn't matter but the config structure requires something here
 ({ffi.Pointer<StartResharedRes> machine, String encoded}) startReshared({
+  required String newMultisigName,
   required String resharerConfig,
   required String myName,
   required List<String> resharerStarts,
 }) {
-  final stringViewPointer = calloc<StringView>();
-  stringViewPointer.ref.ptr = myName.toNativeUtf8().cast<ffi.Uint8>();
-  stringViewPointer.ref.len = myName.length;
+  final newMultisigNamePointer = calloc<StringView>();
+  newMultisigNamePointer.ref.ptr = myName.toNativeUtf8().cast<ffi.Uint8>();
+  newMultisigNamePointer.ref.len = myName.length;
+
+  final myNamePointer = calloc<StringView>();
+  myNamePointer.ref.ptr = myName.toNativeUtf8().cast<ffi.Uint8>();
+  myNamePointer.ref.len = myName.length;
 
   final resharerConfigPointer = decodeResharerConfig(
     resharerConfig: resharerConfig,
@@ -754,14 +770,17 @@ ffi.Pointer<ResharerConfig> decodeResharerConfig({
   }
 
   final result = _bindings.start_reshared(
+    newMultisigNamePointer.ref,
     resharerConfigPointer,
-    stringViewPointer.ref,
+    myNamePointer.ref,
     resharerStartsPointer,
   );
 
   calloc.free(resharerStartsPointer);
-  calloc.free(stringViewPointer.ref.ptr);
-  calloc.free(stringViewPointer);
+  calloc.free(newMultisigNamePointer.ref.ptr);
+  calloc.free(newMultisigNamePointer);
+  calloc.free(myNamePointer.ref.ptr);
+  calloc.free(myNamePointer);
 
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
@@ -804,7 +823,11 @@ String completeResharer({
   }
 }
 
-String completeReshared({
+({
+  String multisigConfig,
+  String serializedKeys,
+  String resharedId,
+}) completeReshared({
   required StartResharedRes prior,
   required List<String> resharerCompletes,
 }) {
@@ -827,6 +850,16 @@ String completeReshared({
   if (result.err != SUCCESS) {
     throw FrostdartException(errorCode: result.err);
   } else {
-    return serializeKeys(keys: result.value);
+    final id = result.value.ref.id.toDartString();
+    freeOwnedString(result.value.ref.id);
+    return (
+      serializedKeys: serializeKeys(
+        keys: result.value.ref.keys,
+      ),
+      multisigConfig: encodeMultisigConfig(
+        multisigConfigPointer: result.value.ref.config,
+      ),
+      resharedId: id,
+    );
   }
 }
diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index f0fc5c0..206cbc4 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -116,6 +116,35 @@ class FrostdartBindings {
   late final _multisig_salt = _multisig_saltPtr.asFunction<
       ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<MultisigConfig>)>();
 
+  OwnedString encode_multisig_config(
+    ffi.Pointer<MultisigConfig> self,
+  ) {
+    return _encode_multisig_config(
+      self,
+    );
+  }
+
+  late final _encode_multisig_configPtr = _lookup<
+      ffi.NativeFunction<
+          OwnedString Function(
+              ffi.Pointer<MultisigConfig>)>>('encode_multisig_config');
+  late final _encode_multisig_config = _encode_multisig_configPtr
+      .asFunction<OwnedString Function(ffi.Pointer<MultisigConfig>)>();
+
+  CResult_MultisigConfig decode_multisig_config(
+    StringView str,
+  ) {
+    return _decode_multisig_config(
+      str,
+    );
+  }
+
+  late final _decode_multisig_configPtr =
+      _lookup<ffi.NativeFunction<CResult_MultisigConfig Function(StringView)>>(
+          'decode_multisig_config');
+  late final _decode_multisig_config = _decode_multisig_configPtr
+      .asFunction<CResult_MultisigConfig Function(StringView)>();
+
   ffi.Pointer<MultisigConfig> multisig_config(
     ffi.Pointer<MultisigConfigWithName> self,
   ) {
@@ -175,20 +204,6 @@ class FrostdartBindings {
       CResult_MultisigConfigRes Function(
           ffi.Pointer<ffi.Uint8>, int, int, ffi.Pointer<StringView>, int)>();
 
-  CResult_MultisigConfig decode_multisig_config(
-    StringView config,
-  ) {
-    return _decode_multisig_config(
-      config,
-    );
-  }
-
-  late final _decode_multisig_configPtr =
-      _lookup<ffi.NativeFunction<CResult_MultisigConfig Function(StringView)>>(
-          'decode_multisig_config');
-  late final _decode_multisig_config = _decode_multisig_configPtr
-      .asFunction<CResult_MultisigConfig Function(StringView)>();
-
   CResult_StartKeyGenRes start_key_gen(
     ffi.Pointer<MultisigConfig> config,
     StringView my_name,
@@ -834,11 +849,13 @@ class FrostdartBindings {
           ffi.Pointer<ThresholdKeysWrapper>, ffi.Pointer<ResharerConfig>)>();
 
   CResult_StartResharedRes start_reshared(
+    StringView multisig_name,
     ffi.Pointer<ResharerConfig> resharer_config,
     StringView my_name,
     ffi.Pointer<StringView> resharer_starts,
   ) {
     return _start_reshared(
+      multisig_name,
       resharer_config,
       my_name,
       resharer_starts,
@@ -847,11 +864,14 @@ class FrostdartBindings {
 
   late final _start_resharedPtr = _lookup<
       ffi.NativeFunction<
-          CResult_StartResharedRes Function(ffi.Pointer<ResharerConfig>,
-              StringView, ffi.Pointer<StringView>)>>('start_reshared');
+          CResult_StartResharedRes Function(
+              StringView,
+              ffi.Pointer<ResharerConfig>,
+              StringView,
+              ffi.Pointer<StringView>)>>('start_reshared');
   late final _start_reshared = _start_resharedPtr.asFunction<
-      CResult_StartResharedRes Function(
-          ffi.Pointer<ResharerConfig>, StringView, ffi.Pointer<StringView>)>();
+      CResult_StartResharedRes Function(StringView, ffi.Pointer<ResharerConfig>,
+          StringView, ffi.Pointer<StringView>)>();
 
   CResult_OwnedString complete_resharer(
     StartResharerRes machine,
@@ -871,7 +891,7 @@ class FrostdartBindings {
       CResult_OwnedString Function(
           StartResharerRes, ffi.Pointer<StringView>)>();
 
-  CResult_ThresholdKeysWrapper complete_reshared(
+  CResult_ResharedRes complete_reshared(
     StartResharedRes prior,
     ffi.Pointer<StringView> resharer_completes,
   ) {
@@ -883,10 +903,10 @@ class FrostdartBindings {
 
   late final _complete_resharedPtr = _lookup<
       ffi.NativeFunction<
-          CResult_ThresholdKeysWrapper Function(
+          CResult_ResharedRes Function(
               StartResharedRes, ffi.Pointer<StringView>)>>('complete_reshared');
   late final _complete_reshared = _complete_resharedPtr.asFunction<
-      CResult_ThresholdKeysWrapper Function(
+      CResult_ResharedRes Function(
           StartResharedRes, ffi.Pointer<StringView>)>();
 }
 
@@ -938,6 +958,13 @@ final class StringView extends ffi.Struct {
   external int len;
 }
 
+final class CResult_MultisigConfig extends ffi.Struct {
+  external ffi.Pointer<MultisigConfig> value;
+
+  @ffi.Uint8()
+  external int err;
+}
+
 final class MultisigConfigWithName extends ffi.Struct {
   external ffi.Pointer<MultisigConfig> config;
 
@@ -957,13 +984,6 @@ final class CResult_MultisigConfigRes extends ffi.Struct {
   external int err;
 }
 
-final class CResult_MultisigConfig extends ffi.Struct {
-  external ffi.Pointer<MultisigConfig> value;
-
-  @ffi.Uint8()
-  external int err;
-}
-
 final class StartKeyGenRes extends ffi.Struct {
   external OwnedString seed;
 
@@ -1128,6 +1148,8 @@ final class StartResharedRes extends ffi.Struct {
   @ffi.UintPtr()
   external int resharers_len;
 
+  external ffi.Pointer<MultisigConfig> multisig_config;
+
   external ffi.Pointer<OpaqueResharedMachine> machine;
 
   external OwnedString encoded;
@@ -1140,6 +1162,21 @@ final class CResult_StartResharedRes extends ffi.Struct {
   external int err;
 }
 
+final class ResharedRes extends ffi.Struct {
+  external ffi.Pointer<MultisigConfig> config;
+
+  external OwnedString id;
+
+  external ffi.Pointer<ThresholdKeysWrapper> keys;
+}
+
+final class CResult_ResharedRes extends ffi.Struct {
+  external ffi.Pointer<ResharedRes> value;
+
+  @ffi.Uint8()
+  external int err;
+}
+
 const int LANGUAGE_ENGLISH = 1;
 
 const int LANGUAGE_CHINESE_SIMPLIFIED = 2;
@@ -1200,6 +1237,8 @@ const int WRONG_KEYS_ERROR = 69;
 
 const int INVALID_PREPROCESS_ERROR = 70;
 
+const int FEE_ERROR = 71;
+
 const int INVALID_PARTICIPANTS_AMOUNT_ERROR = 81;
 
 const int DUPLICATED_PARTICIPANT_ERROR = 82;
diff --git a/lib/util.dart b/lib/util.dart
index d4c630a..fb38db5 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -79,6 +79,8 @@ String getErrorName(int errorCode) {
       return 'WRONG_KEYS_ERROR';
     case INVALID_PREPROCESS_ERROR:
       return 'INVALID_PREPROCESS_ERROR';
+    case FEE_ERROR:
+      return 'FEE_ERROR';
     case INVALID_PARTICIPANTS_AMOUNT_ERROR:
       return 'INVALID_PARTICIPANTS_AMOUNT_ERROR';
     case DUPLICATED_PARTICIPANT_ERROR:
diff --git a/src/serai b/src/serai
index 84ec308..3409add 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 84ec308624b8fb21c0e4c25b7906fc35abc6cf56
+Subproject commit 3409addc71ec33ccf2ea382477bf5801d87ca59a

From a562fcb2b4a1ab7d3b1bcfa61994d6a5969f2f49 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 26 Aug 2023 14:56:11 -0600
Subject: [PATCH 46/49] update ref and bindings

---
 lib/frostdart_bindings_generated.dart | 42 +++++++++++++--------------
 src/serai                             |  2 +-
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 206cbc4..08dfe3c 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -131,20 +131,6 @@ class FrostdartBindings {
   late final _encode_multisig_config = _encode_multisig_configPtr
       .asFunction<OwnedString Function(ffi.Pointer<MultisigConfig>)>();
 
-  CResult_MultisigConfig decode_multisig_config(
-    StringView str,
-  ) {
-    return _decode_multisig_config(
-      str,
-    );
-  }
-
-  late final _decode_multisig_configPtr =
-      _lookup<ffi.NativeFunction<CResult_MultisigConfig Function(StringView)>>(
-          'decode_multisig_config');
-  late final _decode_multisig_config = _decode_multisig_configPtr
-      .asFunction<CResult_MultisigConfig Function(StringView)>();
-
   ffi.Pointer<MultisigConfig> multisig_config(
     ffi.Pointer<MultisigConfigWithName> self,
   ) {
@@ -204,6 +190,20 @@ class FrostdartBindings {
       CResult_MultisigConfigRes Function(
           ffi.Pointer<ffi.Uint8>, int, int, ffi.Pointer<StringView>, int)>();
 
+  CResult_MultisigConfig decode_multisig_config(
+    StringView config,
+  ) {
+    return _decode_multisig_config(
+      config,
+    );
+  }
+
+  late final _decode_multisig_configPtr =
+      _lookup<ffi.NativeFunction<CResult_MultisigConfig Function(StringView)>>(
+          'decode_multisig_config');
+  late final _decode_multisig_config = _decode_multisig_configPtr
+      .asFunction<CResult_MultisigConfig Function(StringView)>();
+
   CResult_StartKeyGenRes start_key_gen(
     ffi.Pointer<MultisigConfig> config,
     StringView my_name,
@@ -958,13 +958,6 @@ final class StringView extends ffi.Struct {
   external int len;
 }
 
-final class CResult_MultisigConfig extends ffi.Struct {
-  external ffi.Pointer<MultisigConfig> value;
-
-  @ffi.Uint8()
-  external int err;
-}
-
 final class MultisigConfigWithName extends ffi.Struct {
   external ffi.Pointer<MultisigConfig> config;
 
@@ -984,6 +977,13 @@ final class CResult_MultisigConfigRes extends ffi.Struct {
   external int err;
 }
 
+final class CResult_MultisigConfig extends ffi.Struct {
+  external ffi.Pointer<MultisigConfig> value;
+
+  @ffi.Uint8()
+  external int err;
+}
+
 final class StartKeyGenRes extends ffi.Struct {
   external OwnedString seed;
 
diff --git a/src/serai b/src/serai
index 3409add..3e37b6d 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 3409addc71ec33ccf2ea382477bf5801d87ca59a
+Subproject commit 3e37b6d1cd78ae60a2b0e71af3985f299362c073

From 43bf48e70585eb9617188bf2e6da68223d3764a0 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 26 Aug 2023 19:47:47 -0600
Subject: [PATCH 47/49] added some comments

---
 lib/frostdart.dart | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/frostdart.dart b/lib/frostdart.dart
index e3df752..cc22e17 100644
--- a/lib/frostdart.dart
+++ b/lib/frostdart.dart
@@ -741,6 +741,7 @@ ffi.Pointer<ResharerConfig> decodeResharerConfig({
   }
 }
 
+/// expects [resharerStarts] of length equal to resharers.
 /// [newMultisigName] doesn't matter but the config structure requires something here
 ({ffi.Pointer<StartResharedRes> machine, String encoded}) startReshared({
   required String newMultisigName,
@@ -792,6 +793,7 @@ ffi.Pointer<ResharerConfig> decodeResharerConfig({
   }
 }
 
+/// expects [encryptionKeysOfResharedTo] of length equal to new participants
 String completeResharer({
   required StartResharerRes machine,
   required List<String> encryptionKeysOfResharedTo,
@@ -823,6 +825,7 @@ String completeResharer({
   }
 }
 
+/// expects [resharerCompletes] of length equal to resharers
 ({
   String multisigConfig,
   String serializedKeys,

From eabf42d07c28ebe215376f9d85f5d5045cebe895 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 26 Aug 2023 20:38:58 -0600
Subject: [PATCH 48/49] update ref and bindings

---
 lib/frostdart_bindings_generated.dart | 3 +++
 src/serai                             | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/lib/frostdart_bindings_generated.dart b/lib/frostdart_bindings_generated.dart
index 08dfe3c..e689437 100644
--- a/lib/frostdart_bindings_generated.dart
+++ b/lib/frostdart_bindings_generated.dart
@@ -1150,6 +1150,9 @@ final class StartResharedRes extends ffi.Struct {
 
   external ffi.Pointer<MultisigConfig> multisig_config;
 
+  @ffi.Uint16()
+  external int my_i;
+
   external ffi.Pointer<OpaqueResharedMachine> machine;
 
   external OwnedString encoded;
diff --git a/src/serai b/src/serai
index 3e37b6d..4069593 160000
--- a/src/serai
+++ b/src/serai
@@ -1 +1 @@
-Subproject commit 3e37b6d1cd78ae60a2b0e71af3985f299362c073
+Subproject commit 40695938ed32c9c5074edbc12041f3ddb9134834

From 2c4041fec6af6c74899d4df393ecb6ca3e5a74e5 Mon Sep 17 00:00:00 2001
From: julian-CStack <97684800+julian-CStack@users.noreply.github.com>
Date: Tue, 29 Aug 2023 06:40:21 -0600
Subject: [PATCH 49/49] Update README.md

---
 README.md | 93 +++++--------------------------------------------------
 1 file changed, 7 insertions(+), 86 deletions(-)

diff --git a/README.md b/README.md
index 4982e83..834c8f5 100644
--- a/README.md
+++ b/README.md
@@ -1,92 +1,13 @@
 # frostdart
 
-A new Flutter project.
+Dart interface to the Serai FROST multisig implementation
 
-## Getting Started
+## Building
 
-This project is a starting point for a Flutter
-[FFI plugin](https://docs.flutter.dev/development/platform-integration/c-interop),
-a specialized package that includes native code directly invoked with Dart FFI.
-
-## Project structure
-
-This template uses the following structure:
-
-* `src`: Contains the native source code, and a CmakeFile.txt file for building
-  that source code into a dynamic library.
-
-* `lib`: Contains the Dart code that defines the API of the plugin, and which
-  calls into the native code using `dart:ffi`.
-
-* platform folders (`android`, `ios`, `windows`, etc.): Contains the build files
-  for building and bundling the native code library with the platform application.
-
-## Building and bundling native code
-
-The `pubspec.yaml` specifies FFI plugins as follows:
-
-```yaml
-  plugin:
-    platforms:
-      some_platform:
-        ffiPlugin: true
-```
-
-This configuration invokes the native build for the various target platforms
-and bundles the binaries in Flutter applications using these FFI plugins.
-
-This can be combined with dartPluginClass, such as when FFI is used for the
-implementation of one platform in a federated plugin:
-
-```yaml
-  plugin:
-    implements: some_other_plugin
-    platforms:
-      some_platform:
-        dartPluginClass: SomeClass
-        ffiPlugin: true
 ```
-
-A plugin can have both FFI and method channels:
-
-```yaml
-  plugin:
-    platforms:
-      some_platform:
-        pluginClass: SomeName
-        ffiPlugin: true
+git clone https://www.github.com/cypherstack/frostdart
+cd frostdart
+git submodule update --init --recursive
+cd scripts/[platform]
+./build_all.sh
 ```
-
-The native build systems that are invoked by FFI (and method channel) plugins are:
-
-* For Android: Gradle, which invokes the Android NDK for native builds.
-  * See the documentation in android/build.gradle.
-* For iOS and MacOS: Xcode, via CocoaPods.
-  * See the documentation in ios/frostdart.podspec.
-  * See the documentation in macos/frostdart.podspec.
-* For Linux and Windows: CMake.
-  * See the documentation in linux/CMakeLists.txt.
-  * See the documentation in windows/CMakeLists.txt.
-
-## Binding to native code
-
-To use the native code, bindings in Dart are needed.
-To avoid writing these by hand, they are generated from the header file
-(`src/frostdart.h`) by `package:ffigen`.
-Regenerate the bindings by running `flutter pub run ffigen --config ffigen.yaml`.
-
-## Invoking native code
-
-Very short-running native functions can be directly invoked from any isolate.
-For example, see `sum` in `lib/frostdart.dart`.
-
-Longer-running functions should be invoked on a helper isolate to avoid
-dropping frames in Flutter applications.
-For example, see `sumAsync` in `lib/frostdart.dart`.
-
-## Flutter help
-
-For help getting started with Flutter, view our
-[online documentation](https://flutter.dev/docs), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
-
