frost swb integration fixes

This commit is contained in:
julian 2024-01-30 18:08:31 -06:00
parent 2e6ac40e20
commit 0d3ef1bfc4

View file

@ -10,11 +10,10 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:frostdart/frostdart_bindings_generated.dart'; import 'package:frostdart/frostdart.dart' as frost;
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stack_wallet_backup/stack_wallet_backup.dart'; import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/db/hive/db.dart';
@ -44,6 +43,7 @@ import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/models/frost_wallet_info.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/impl/bitcoin_frost_wallet.dart'; import 'package:stackwallet/wallets/wallet/impl/bitcoin_frost_wallet.dart';
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart'; import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
@ -309,21 +309,21 @@ abstract class SWB {
} else if (wallet is BitcoinFrostWallet) { } else if (wallet is BitcoinFrostWallet) {
String? keys = await wallet.getSerializedKeys(); String? keys = await wallet.getSerializedKeys();
String? config = await wallet.getMultisigConfig(); String? config = await wallet.getMultisigConfig();
String myName = wallet.frostInfo.myName;
if (keys == null || config == null) { if (keys == null || config == null) {
String err = "${wallet.info.coin.name} wallet ${wallet.info.name} " String err = "${wallet.info.coin.name} wallet ${wallet.info.name} "
"has null keys or config"; "has null keys or config";
Logging.instance.log(err, level: LogLevel.Fatal); Logging.instance.log(err, level: LogLevel.Fatal);
throw Exception(err); throw Exception(err);
} }
//This case should never actually happen in practice unless the whole
// wallet is somehow corrupt
// TODO [prio=low]: solve case in which either keys or config is null. // TODO [prio=low]: solve case in which either keys or config is null.
// Format keys & config as a JSON string and set otherDataJsonString. // Format keys & config as a JSON string and set otherDataJsonString.
Map<String, dynamic> otherData = {}; Map<String, dynamic> frostData = {};
otherData["keys"] = keys; frostData["keys"] = keys;
otherData["config"] = config; frostData["config"] = config;
otherData["myName"] = myName; backupWallet['frostWalletData'] = jsonEncode(frostData);
backupWallet['otherDataJsonString'] = jsonEncode(otherData);
} }
backupWallet['coinName'] = wallet.info.coin.name; backupWallet['coinName'] = wallet.info.coin.name;
backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight; backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight;
@ -430,82 +430,38 @@ abstract class SWB {
); );
try { try {
final Wallet wallet; String? serializedKeys;
String? multisigConfig;
if (info.coin == Coin.bitcoinFrost || if (info.coin.isFrost) {
info.coin == Coin.bitcoinFrostTestNet) {
// Decode info.otherDataJsonString for Frost recovery info. // Decode info.otherDataJsonString for Frost recovery info.
final otherData = jsonDecode(info.otherDataJsonString!); final frostData = jsonDecode(walletbackup["frostWalletData"] as String);
final String serializedKeys = otherData["keys"] as String; serializedKeys = frostData["keys"] as String;
final String multisigConfig = otherData["config"] as String; multisigConfig = frostData["config"] as String;
final String myName = otherData["myName"] as String;
// Start Frost key generation. final myNameIndex = frost.getParticipantIndexFromKeys(
final frostStartKeyGenData = Frost.startKeyGeneration( serializedKeys: serializedKeys,
);
final participants = Frost.getParticipants(
multisigConfig: multisigConfig, multisigConfig: multisigConfig,
);
final myName = participants[myNameIndex];
final frostInfo = FrostWalletInfo(
walletId: info.walletId,
knownSalts: [],
participants: participants,
myName: myName, myName: myName,
threshold: frost.multisigThreshold(
multisigConfig: multisigConfig,
),
); );
// Generate shares. await MainDB.instance.isar.writeTxn(() async {
final ({ await MainDB.instance.isar.frostWalletInfo.put(frostInfo);
Pointer<SecretSharesRes> secretSharesResPtr, });
String share
}) frostSecretSharesData;
try {
frostSecretSharesData = Frost.generateSecretShares(
multisigConfigWithNamePtr:
frostStartKeyGenData.multisigConfigWithNamePtr,
mySeed: frostStartKeyGenData.seed,
secretShareMachineWrapperPtr:
frostStartKeyGenData.secretShareMachineWrapperPtr,
commitments: [frostStartKeyGenData.commitments],
);
} catch (e, s) {
Logging.instance.log(
"$e\n$s",
level: LogLevel.Fatal,
);
throw Error();
} }
// Get shares. final wallet = await Wallet.create(
final shares = [
frostSecretSharesData.share,
];
// Complete Frost key generation.
final frostCompleteKeyGenData = Frost.completeKeyGeneration(
multisigConfigWithNamePtr:
frostStartKeyGenData.multisigConfigWithNamePtr,
secretSharesResPtr: frostSecretSharesData.secretSharesResPtr,
shares: [frostSecretSharesData.share], // TODO [prio=high]: verify.
);
wallet = await Wallet.create(
walletInfo: info,
mainDB: MainDB.instance,
secureStorageInterface: secureStorageInterface,
nodeService: nodeService,
prefs: prefs,
);
await (wallet as BitcoinFrostWallet).initializeNewFrost(
mnemonic: frostStartKeyGenData.seed,
multisigConfig: multisigConfig,
recoveryString: frostCompleteKeyGenData.recoveryString,
serializedKeys: serializedKeys,
multisigId: frostCompleteKeyGenData.multisigId,
myName: myName,
participants: Frost.getParticipants(
multisigConfig: multisigConfig,
),
threshold: Frost.getThreshold(
multisigConfig: multisigConfig,
),
);
} else {
wallet = await Wallet.create(
walletInfo: info, walletInfo: info,
mainDB: MainDB.instance, mainDB: MainDB.instance,
secureStorageInterface: secureStorageInterface, secureStorageInterface: secureStorageInterface,
@ -515,7 +471,6 @@ abstract class SWB {
mnemonicPassphrase: mnemonicPassphrase, mnemonicPassphrase: mnemonicPassphrase,
privateKey: privateKey, privateKey: privateKey,
); );
}
await wallet.init(); await wallet.init();
@ -527,8 +482,16 @@ abstract class SWB {
Future<void>? restoringFuture; Future<void>? restoringFuture;
if (!(wallet is CwBasedInterface || wallet is EpiccashWallet)) { if (!(wallet is CwBasedInterface || wallet is EpiccashWallet)) {
if (wallet is BitcoinFrostWallet) {
restoringFuture = wallet.recover(
isRescan: false,
multisigConfig: multisigConfig!,
serializedKeys: serializedKeys!,
);
} else {
restoringFuture = wallet.recover(isRescan: false); restoringFuture = wallet.recover(isRescan: false);
} }
}
uiState?.update( uiState?.update(
walletId: info.walletId, walletId: info.walletId,