mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-22 10:34:32 +00:00
Merge remote-tracking branch 'origin/testing' into tor
This commit is contained in:
commit
6afe034dc4
9 changed files with 450 additions and 273 deletions
|
@ -8,10 +8,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
// import 'package:coinlib_flutter/coinlib_flutter.dart';
|
||||
import 'package:coinlib_flutter/coinlib_flutter.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
|
||||
|
@ -19,49 +16,19 @@ class SigningData {
|
|||
SigningData({
|
||||
required this.derivePathType,
|
||||
required this.utxo,
|
||||
this.output,
|
||||
this.keyPair,
|
||||
this.redeemScript,
|
||||
});
|
||||
|
||||
final DerivePathType derivePathType;
|
||||
final UTXO utxo;
|
||||
Uint8List? output;
|
||||
ECPair? keyPair;
|
||||
Uint8List? redeemScript;
|
||||
HDPrivateKey? keyPair;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "SigningData{\n"
|
||||
" derivePathType: $derivePathType,\n"
|
||||
" utxo: $utxo,\n"
|
||||
" output: $output,\n"
|
||||
" keyPair: $keyPair,\n"
|
||||
" redeemScript: $redeemScript,\n"
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
||||
// class SigningData {
|
||||
// SigningData({
|
||||
// required this.derivePathType,
|
||||
// required this.utxo,
|
||||
// this.keyPair,
|
||||
// this.redeemScript,
|
||||
// });
|
||||
//
|
||||
// final DerivePathType derivePathType;
|
||||
// final UTXO utxo;
|
||||
// ({ECPrivateKey privateKey, ECPublicKey publicKey})? keyPair;
|
||||
// Uint8List? redeemScript;
|
||||
//
|
||||
// @override
|
||||
// String toString() {
|
||||
// return "SigningData{\n"
|
||||
// " derivePathType: $derivePathType,\n"
|
||||
// " utxo: $utxo,\n"
|
||||
// " keyPair: $keyPair,\n"
|
||||
// " redeemScript: $redeemScript,\n"
|
||||
// "}";
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/banano.dart';
|
||||
|
@ -38,34 +36,6 @@ class AddressUtils {
|
|||
return '${address.substring(0, 5)}...${address.substring(address.length - 5)}';
|
||||
}
|
||||
|
||||
/// attempts to convert a string to a valid scripthash
|
||||
///
|
||||
/// Returns the scripthash or throws an exception on invalid firo address
|
||||
static String convertToScriptHash(
|
||||
String address,
|
||||
NetworkType network, [
|
||||
String overridePrefix = "",
|
||||
]) {
|
||||
try {
|
||||
final output =
|
||||
Address.addressToOutputScript(address, network, overridePrefix);
|
||||
final hash = sha256.convert(output.toList(growable: false)).toString();
|
||||
|
||||
final chars = hash.split("");
|
||||
final reversedPairs = <String>[];
|
||||
// TODO find a better/faster way to do this?
|
||||
var i = chars.length - 1;
|
||||
while (i > 0) {
|
||||
reversedPairs.add(chars[i - 1]);
|
||||
reversedPairs.add(chars[i]);
|
||||
i -= 2;
|
||||
}
|
||||
return reversedPairs.join("");
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static bool validateAddress(String address, Coin coin) {
|
||||
//This calls the validate address for each crypto coin, validateAddress is
|
||||
//only used in 2 places, so I just replaced the old functionality here
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
import 'package:bip32/bip32.dart' as bip32;
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
|
@ -19,25 +18,17 @@ abstract class Bip32Utils {
|
|||
static bip32.BIP32 getBip32RootSync(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType networkType,
|
||||
bip32.NetworkType networkType,
|
||||
) {
|
||||
final seed = bip39.mnemonicToSeed(mnemonic, passphrase: mnemonicPassphrase);
|
||||
final _networkType = bip32.NetworkType(
|
||||
wif: networkType.wif,
|
||||
bip32: bip32.Bip32Type(
|
||||
public: networkType.bip32.public,
|
||||
private: networkType.bip32.private,
|
||||
),
|
||||
);
|
||||
|
||||
final root = bip32.BIP32.fromSeed(seed, _networkType);
|
||||
final root = bip32.BIP32.fromSeed(seed, networkType);
|
||||
return root;
|
||||
}
|
||||
|
||||
static Future<bip32.BIP32> getBip32Root(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType networkType,
|
||||
bip32.NetworkType networkType,
|
||||
) async {
|
||||
final root = await compute(
|
||||
_getBip32RootWrapper,
|
||||
|
@ -52,7 +43,7 @@ abstract class Bip32Utils {
|
|||
|
||||
/// wrapper for compute()
|
||||
static bip32.BIP32 _getBip32RootWrapper(
|
||||
Tuple3<String, String, NetworkType> args,
|
||||
Tuple3<String, String, bip32.NetworkType> args,
|
||||
) {
|
||||
return getBip32RootSync(
|
||||
args.item1,
|
||||
|
@ -97,7 +88,7 @@ abstract class Bip32Utils {
|
|||
static bip32.BIP32 getBip32NodeSync(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType network,
|
||||
bip32.NetworkType network,
|
||||
String derivePath,
|
||||
) {
|
||||
final root = getBip32RootSync(mnemonic, mnemonicPassphrase, network);
|
||||
|
@ -109,7 +100,7 @@ abstract class Bip32Utils {
|
|||
static Future<bip32.BIP32> getBip32Node(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType networkType,
|
||||
bip32.NetworkType networkType,
|
||||
String derivePath,
|
||||
) async {
|
||||
final node = await compute(
|
||||
|
@ -126,7 +117,7 @@ abstract class Bip32Utils {
|
|||
|
||||
/// wrapper for compute()
|
||||
static bip32.BIP32 _getBip32NodeWrapper(
|
||||
Tuple4<String, String, NetworkType, String> args,
|
||||
Tuple4<String, String, bip32.NetworkType, String> args,
|
||||
) {
|
||||
return getBip32NodeSync(
|
||||
args.item1,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bitcoindart/bitcoindart.dart' as bitcoindart;
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
|
||||
|
@ -7,6 +9,7 @@ import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart
|
|||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||
import 'package:stackwallet/models/signing_data.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/extensions/impl/uint8_list.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/particl.dart';
|
||||
|
@ -340,20 +343,92 @@ class ParticlWallet extends Bip39HDWallet
|
|||
Logging.instance.log("Starting Particl buildTransaction ----------",
|
||||
level: LogLevel.Info);
|
||||
|
||||
// TODO: use coinlib
|
||||
// TODO: use coinlib (For this we need coinlib to support particl)
|
||||
|
||||
final convertedNetwork = bitcoindart.NetworkType(
|
||||
messagePrefix: cryptoCurrency.networkParams.messagePrefix,
|
||||
bech32: cryptoCurrency.networkParams.bech32Hrp,
|
||||
bip32: bitcoindart.Bip32Type(
|
||||
public: cryptoCurrency.networkParams.pubHDPrefix,
|
||||
private: cryptoCurrency.networkParams.privHDPrefix,
|
||||
),
|
||||
pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
scriptHash: cryptoCurrency.networkParams.p2shPrefix,
|
||||
wif: cryptoCurrency.networkParams.wifPrefix,
|
||||
);
|
||||
|
||||
final List<({Uint8List? output, Uint8List? redeem})> extraData = [];
|
||||
for (int i = 0; i < utxoSigningData.length; i++) {
|
||||
final sd = utxoSigningData[i];
|
||||
|
||||
final pubKey = sd.keyPair!.publicKey.data;
|
||||
final bitcoindart.PaymentData? data;
|
||||
Uint8List? redeem, output;
|
||||
|
||||
switch (sd.derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
data = bitcoindart
|
||||
.P2PKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip49:
|
||||
final p2wpkh = bitcoindart
|
||||
.P2WPKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
redeem = p2wpkh.output;
|
||||
data = bitcoindart
|
||||
.P2SH(
|
||||
data: bitcoindart.PaymentData(redeem: p2wpkh),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip84:
|
||||
// input = coinlib.P2WPKHInput(
|
||||
// prevOut: coinlib.OutPoint.fromHex(sd.utxo.txid, sd.utxo.vout),
|
||||
// publicKey: keys.publicKey,
|
||||
// );
|
||||
data = bitcoindart
|
||||
.P2WPKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip86:
|
||||
data = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
|
||||
// sd.output = input.script!.compiled;
|
||||
|
||||
if (sd.derivePathType != DerivePathType.bip86) {
|
||||
output = data!.output!;
|
||||
}
|
||||
|
||||
extraData.add((output: output, redeem: redeem));
|
||||
}
|
||||
|
||||
final txb = bitcoindart.TransactionBuilder(
|
||||
network: bitcoindart.NetworkType(
|
||||
messagePrefix: cryptoCurrency.networkParams.messagePrefix,
|
||||
bech32: cryptoCurrency.networkParams.bech32Hrp,
|
||||
bip32: bitcoindart.Bip32Type(
|
||||
public: cryptoCurrency.networkParams.pubHDPrefix,
|
||||
private: cryptoCurrency.networkParams.privHDPrefix,
|
||||
),
|
||||
pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
scriptHash: cryptoCurrency.networkParams.p2shPrefix,
|
||||
wif: cryptoCurrency.networkParams.wifPrefix,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
);
|
||||
const version = 160; // buildTransaction overridden for Particl to set this.
|
||||
// TODO: [prio=low] refactor overridden buildTransaction to use eg. cryptocurrency.networkParams.txVersion.
|
||||
|
@ -370,7 +445,7 @@ class ParticlWallet extends Bip39HDWallet
|
|||
txid,
|
||||
utxoSigningData[i].utxo.vout,
|
||||
null,
|
||||
utxoSigningData[i].output!,
|
||||
extraData[i].output!,
|
||||
cryptoCurrency.networkParams.bech32Hrp,
|
||||
);
|
||||
|
||||
|
@ -427,9 +502,13 @@ class ParticlWallet extends Bip39HDWallet
|
|||
for (var i = 0; i < utxoSigningData.length; i++) {
|
||||
txb.sign(
|
||||
vin: i,
|
||||
keyPair: utxoSigningData[i].keyPair!,
|
||||
keyPair: bitcoindart.ECPair.fromPrivateKey(
|
||||
utxoSigningData[i].keyPair!.privateKey.data,
|
||||
network: convertedNetwork,
|
||||
compressed: utxoSigningData[i].keyPair!.privateKey.compressed,
|
||||
),
|
||||
witnessValue: utxoSigningData[i].utxo.value,
|
||||
redeemScript: utxoSigningData[i].redeemScript,
|
||||
redeemScript: extraData[i].redeem,
|
||||
overridePrefix: cryptoCurrency.networkParams.bech32Hrp,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:bitbox/bitbox.dart' as bitbox;
|
||||
import 'package:bitbox/src/utils/network.dart' as bitbox_utils;
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart';
|
||||
|
@ -89,8 +90,17 @@ mixin BCashInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
try {
|
||||
// Sign the transaction accordingly
|
||||
for (int i = 0; i < utxoSigningData.length; i++) {
|
||||
final bitboxEC = bitbox.ECPair.fromWIF(
|
||||
utxoSigningData[i].keyPair!.toWIF(),
|
||||
final bitboxEC = bitbox.ECPair.fromPrivateKey(
|
||||
utxoSigningData[i].keyPair!.privateKey.data,
|
||||
network: bitbox_utils.Network(
|
||||
cryptoCurrency.networkParams.privHDPrefix,
|
||||
cryptoCurrency.networkParams.pubHDPrefix,
|
||||
cryptoCurrency.network == CryptoCurrencyNetwork.test,
|
||||
cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
cryptoCurrency.networkParams.wifPrefix,
|
||||
cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
),
|
||||
compressed: utxoSigningData[i].keyPair!.privateKey.compressed,
|
||||
);
|
||||
|
||||
builder.sign(
|
||||
|
|
|
@ -2,8 +2,6 @@ import 'dart:async';
|
|||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bip47/src/util.dart';
|
||||
import 'package:bitcoindart/bitcoindart.dart' as bitcoindart;
|
||||
import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib;
|
||||
import 'package:electrum_adapter/electrum_adapter.dart' as electrum_adapter;
|
||||
import 'package:electrum_adapter/electrum_adapter.dart';
|
||||
|
@ -22,6 +20,7 @@ import 'package:stackwallet/utilities/amount/amount.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/extensions/extensions.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/paynym_is_api.dart';
|
||||
import 'package:stackwallet/utilities/prefs.dart';
|
||||
|
@ -545,18 +544,6 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
|||
);
|
||||
}
|
||||
|
||||
final convertedNetwork = bitcoindart.NetworkType(
|
||||
messagePrefix: cryptoCurrency.networkParams.messagePrefix,
|
||||
bech32: cryptoCurrency.networkParams.bech32Hrp,
|
||||
bip32: bitcoindart.Bip32Type(
|
||||
public: cryptoCurrency.networkParams.pubHDPrefix,
|
||||
private: cryptoCurrency.networkParams.privHDPrefix,
|
||||
),
|
||||
pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
scriptHash: cryptoCurrency.networkParams.p2shPrefix,
|
||||
wif: cryptoCurrency.networkParams.wifPrefix,
|
||||
);
|
||||
|
||||
final root = await getRootHDNode();
|
||||
|
||||
for (final sd in signingData) {
|
||||
|
@ -597,80 +584,7 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
|||
"Failed to fetch signing data. Local db corrupt. Rescan wallet.");
|
||||
}
|
||||
|
||||
// final coinlib.Input input;
|
||||
|
||||
final pubKey = keys.publicKey.data;
|
||||
final bitcoindart.PaymentData? data;
|
||||
|
||||
switch (sd.derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
// input = coinlib.P2PKHInput(
|
||||
// prevOut: coinlib.OutPoint.fromHex(sd.utxo.txid, sd.utxo.vout),
|
||||
// publicKey: keys.publicKey,
|
||||
// );
|
||||
|
||||
data = bitcoindart
|
||||
.P2PKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip49:
|
||||
final p2wpkh = bitcoindart
|
||||
.P2WPKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
sd.redeemScript = p2wpkh.output;
|
||||
data = bitcoindart
|
||||
.P2SH(
|
||||
data: bitcoindart.PaymentData(redeem: p2wpkh),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip84:
|
||||
// input = coinlib.P2WPKHInput(
|
||||
// prevOut: coinlib.OutPoint.fromHex(sd.utxo.txid, sd.utxo.vout),
|
||||
// publicKey: keys.publicKey,
|
||||
// );
|
||||
data = bitcoindart
|
||||
.P2WPKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip86:
|
||||
data = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
|
||||
// sd.output = input.script!.compiled;
|
||||
|
||||
if (sd.derivePathType != DerivePathType.bip86) {
|
||||
sd.output = data!.output!;
|
||||
}
|
||||
|
||||
sd.keyPair = bitcoindart.ECPair.fromPrivateKey(
|
||||
keys.privateKey.data,
|
||||
compressed: keys.privateKey.compressed,
|
||||
network: convertedNetwork,
|
||||
);
|
||||
sd.keyPair = keys;
|
||||
}
|
||||
|
||||
return signingData;
|
||||
|
@ -705,7 +619,9 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
|||
for (var i = 0; i < utxoSigningData.length; i++) {
|
||||
final txid = utxoSigningData[i].utxo.txid;
|
||||
|
||||
final hash = Uint8List.fromList(txid.fromHex.reversed.toList());
|
||||
final hash = Uint8List.fromList(
|
||||
txid.toUint8ListFromHex.reversed.toList(),
|
||||
);
|
||||
|
||||
final prevOutpoint = coinlib.OutPoint(
|
||||
hash,
|
||||
|
@ -729,30 +645,25 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
|||
case DerivePathType.bch44:
|
||||
input = coinlib.P2PKHInput(
|
||||
prevOut: prevOutpoint,
|
||||
// publicKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
publicKey: coinlib.ECPublicKey(
|
||||
utxoSigningData[i].keyPair!.publicKey,
|
||||
),
|
||||
publicKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
sequence: 0xffffffff - 1,
|
||||
);
|
||||
|
||||
// TODO: fix this as it is (probably) wrong!
|
||||
case DerivePathType.bip49:
|
||||
input = coinlib.P2SHMultisigInput(
|
||||
prevOut: prevOutpoint,
|
||||
program: coinlib.MultisigProgram.decompile(
|
||||
utxoSigningData[i].redeemScript!,
|
||||
),
|
||||
sequence: 0xffffffff - 1,
|
||||
);
|
||||
throw Exception("TODO p2sh");
|
||||
// input = coinlib.P2SHMultisigInput(
|
||||
// prevOut: prevOutpoint,
|
||||
// program: coinlib.MultisigProgram.decompile(
|
||||
// utxoSigningData[i].redeemScript!,
|
||||
// ),
|
||||
// sequence: 0xffffffff - 1,
|
||||
// );
|
||||
|
||||
case DerivePathType.bip84:
|
||||
input = coinlib.P2WPKHInput(
|
||||
prevOut: prevOutpoint,
|
||||
// publicKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
publicKey: coinlib.ECPublicKey(
|
||||
utxoSigningData[i].keyPair!.publicKey,
|
||||
),
|
||||
publicKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
sequence: 0xffffffff - 1,
|
||||
);
|
||||
|
||||
|
@ -825,16 +736,11 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
|||
// Sign the transaction accordingly
|
||||
for (var i = 0; i < utxoSigningData.length; i++) {
|
||||
final value = BigInt.from(utxoSigningData[i].utxo.value);
|
||||
coinlib.ECPrivateKey key = coinlib.ECPrivateKey(
|
||||
utxoSigningData[i].keyPair!.privateKey!,
|
||||
compressed: utxoSigningData[i].keyPair!.compressed,
|
||||
);
|
||||
coinlib.ECPrivateKey key = utxoSigningData[i].keyPair!.privateKey;
|
||||
|
||||
if (clTx.inputs[i] is coinlib.TaprootKeyInput) {
|
||||
final taproot = coinlib.Taproot(
|
||||
internalKey: coinlib.ECPublicKey(
|
||||
utxoSigningData[i].keyPair!.publicKey,
|
||||
),
|
||||
internalKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
);
|
||||
|
||||
key = taproot.tweakPrivateKey(key);
|
||||
|
@ -843,18 +749,9 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
|||
clTx = clTx.sign(
|
||||
inputN: i,
|
||||
value: value,
|
||||
// key: utxoSigningData[i].keyPair!.privateKey,
|
||||
key: key,
|
||||
prevOuts: prevOuts,
|
||||
);
|
||||
|
||||
// txb.sign(
|
||||
// vin: i,
|
||||
// keyPair: utxoSigningData[i].keyPair!,
|
||||
// witnessValue: utxoSigningData[i].utxo.value,
|
||||
// redeemScript: utxoSigningData[i].redeemScript,
|
||||
// overridePrefix: cryptoCurrency.networkParams.bech32Hrp,
|
||||
// );
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logging.instance.log("Caught exception while signing transaction: $e\n$s",
|
||||
|
|
|
@ -742,18 +742,20 @@ mixin LelantusInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
Future<TxData> buildMintTransaction({required TxData txData}) async {
|
||||
final signingData = await fetchBuildTxData(txData.utxos!.toList());
|
||||
|
||||
final txb = bitcoindart.TransactionBuilder(
|
||||
network: bitcoindart.NetworkType(
|
||||
messagePrefix: cryptoCurrency.networkParams.messagePrefix,
|
||||
bech32: cryptoCurrency.networkParams.bech32Hrp,
|
||||
bip32: bitcoindart.Bip32Type(
|
||||
public: cryptoCurrency.networkParams.pubHDPrefix,
|
||||
private: cryptoCurrency.networkParams.privHDPrefix,
|
||||
),
|
||||
pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
scriptHash: cryptoCurrency.networkParams.p2shPrefix,
|
||||
wif: cryptoCurrency.networkParams.wifPrefix,
|
||||
final convertedNetwork = bitcoindart.NetworkType(
|
||||
messagePrefix: cryptoCurrency.networkParams.messagePrefix,
|
||||
bech32: cryptoCurrency.networkParams.bech32Hrp,
|
||||
bip32: bitcoindart.Bip32Type(
|
||||
public: cryptoCurrency.networkParams.pubHDPrefix,
|
||||
private: cryptoCurrency.networkParams.privHDPrefix,
|
||||
),
|
||||
pubKeyHash: cryptoCurrency.networkParams.p2pkhPrefix,
|
||||
scriptHash: cryptoCurrency.networkParams.p2shPrefix,
|
||||
wif: cryptoCurrency.networkParams.wifPrefix,
|
||||
);
|
||||
|
||||
final txb = bitcoindart.TransactionBuilder(
|
||||
network: convertedNetwork,
|
||||
);
|
||||
txb.setVersion(2);
|
||||
|
||||
|
@ -763,11 +765,62 @@ mixin LelantusInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
int amount = 0;
|
||||
// Add transaction inputs
|
||||
for (var i = 0; i < signingData.length; i++) {
|
||||
final pubKey = signingData[i].keyPair!.publicKey.data;
|
||||
final bitcoindart.PaymentData? data;
|
||||
|
||||
switch (signingData[i].derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
data = bitcoindart
|
||||
.P2PKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip49:
|
||||
final p2wpkh = bitcoindart
|
||||
.P2WPKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
data = bitcoindart
|
||||
.P2SH(
|
||||
data: bitcoindart.PaymentData(redeem: p2wpkh),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip84:
|
||||
data = bitcoindart
|
||||
.P2WPKH(
|
||||
data: bitcoindart.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: convertedNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip86:
|
||||
data = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
|
||||
txb.addInput(
|
||||
signingData[i].utxo.txid,
|
||||
signingData[i].utxo.vout,
|
||||
null,
|
||||
signingData[i].output,
|
||||
data!.output!,
|
||||
);
|
||||
amount += signingData[i].utxo.value;
|
||||
}
|
||||
|
@ -782,7 +835,11 @@ mixin LelantusInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
for (var i = 0; i < signingData.length; i++) {
|
||||
txb.sign(
|
||||
vin: i,
|
||||
keyPair: signingData[i].keyPair!,
|
||||
keyPair: bitcoindart.ECPair.fromPrivateKey(
|
||||
signingData[i].keyPair!.privateKey.data,
|
||||
network: convertedNetwork,
|
||||
compressed: signingData[i].keyPair!.privateKey.compressed,
|
||||
),
|
||||
witnessValue: signingData[i].utxo.value,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:bip47/bip47.dart';
|
|||
import 'package:bitcoindart/bitcoindart.dart' as btc_dart;
|
||||
import 'package:bitcoindart/src/utils/constants/op.dart' as op;
|
||||
import 'package:bitcoindart/src/utils/script.dart' as bscript;
|
||||
import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib;
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:pointycastle/digests/sha256.dart';
|
||||
import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart';
|
||||
|
@ -20,6 +21,7 @@ import 'package:stackwallet/utilities/amount/amount.dart';
|
|||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/bip47_utils.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/extensions/extensions.dart';
|
||||
import 'package:stackwallet/utilities/format.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
@ -290,7 +292,13 @@ mixin PaynymInterface<T extends PaynymCurrencyInterface>
|
|||
return _cachedRootNode ??= await Bip32Utils.getBip32Root(
|
||||
(await getMnemonic()),
|
||||
(await getMnemonicPassphrase()),
|
||||
networkType,
|
||||
bip32.NetworkType(
|
||||
wif: networkType.wif,
|
||||
bip32: bip32.Bip32Type(
|
||||
public: networkType.bip32.public,
|
||||
private: networkType.bip32.private,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -701,7 +709,7 @@ mixin PaynymInterface<T extends PaynymCurrencyInterface>
|
|||
final myKeyPair = utxoSigningData.first.keyPair!;
|
||||
|
||||
final S = SecretPoint(
|
||||
myKeyPair.privateKey!,
|
||||
myKeyPair.privateKey.data,
|
||||
targetPaymentCode.notificationPublicKey(),
|
||||
);
|
||||
|
||||
|
@ -719,63 +727,146 @@ mixin PaynymInterface<T extends PaynymCurrencyInterface>
|
|||
]);
|
||||
|
||||
// build a notification tx
|
||||
final txb = btc_dart.TransactionBuilder(network: networkType);
|
||||
txb.setVersion(1);
|
||||
|
||||
txb.addInput(
|
||||
utxo.txid,
|
||||
txPointIndex,
|
||||
null,
|
||||
utxoSigningData.first.output!,
|
||||
final List<coinlib.Output> prevOuts = [];
|
||||
|
||||
coinlib.Transaction clTx = coinlib.Transaction(
|
||||
version: 1,
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
);
|
||||
|
||||
// add rest of possible inputs
|
||||
for (var i = 1; i < utxoSigningData.length; i++) {
|
||||
final utxo = utxoSigningData[i].utxo;
|
||||
txb.addInput(
|
||||
utxo.txid,
|
||||
utxo.vout,
|
||||
null,
|
||||
utxoSigningData[i].output!,
|
||||
for (var i = 0; i < utxoSigningData.length; i++) {
|
||||
final txid = utxoSigningData[i].utxo.txid;
|
||||
|
||||
final hash = Uint8List.fromList(
|
||||
txid.toUint8ListFromHex.reversed.toList(),
|
||||
);
|
||||
|
||||
final prevOutpoint = coinlib.OutPoint(
|
||||
hash,
|
||||
utxoSigningData[i].utxo.vout,
|
||||
);
|
||||
|
||||
final prevOutput = coinlib.Output.fromAddress(
|
||||
BigInt.from(utxoSigningData[i].utxo.value),
|
||||
coinlib.Address.fromString(
|
||||
utxoSigningData[i].utxo.address!,
|
||||
cryptoCurrency.networkParams,
|
||||
),
|
||||
);
|
||||
|
||||
prevOuts.add(prevOutput);
|
||||
|
||||
final coinlib.Input input;
|
||||
|
||||
switch (utxoSigningData[i].derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
case DerivePathType.bch44:
|
||||
input = coinlib.P2PKHInput(
|
||||
prevOut: prevOutpoint,
|
||||
publicKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
sequence: 0xffffffff - 1,
|
||||
);
|
||||
|
||||
// TODO: fix this as it is (probably) wrong! (unlikely used in paynyms)
|
||||
case DerivePathType.bip49:
|
||||
throw Exception("TODO p2sh");
|
||||
// input = coinlib.P2SHMultisigInput(
|
||||
// prevOut: prevOutpoint,
|
||||
// program: coinlib.MultisigProgram.decompile(
|
||||
// utxoSigningData[i].redeemScript!,
|
||||
// ),
|
||||
// sequence: 0xffffffff - 1,
|
||||
// );
|
||||
|
||||
case DerivePathType.bip84:
|
||||
input = coinlib.P2WPKHInput(
|
||||
prevOut: prevOutpoint,
|
||||
publicKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
sequence: 0xffffffff - 1,
|
||||
);
|
||||
|
||||
case DerivePathType.bip86:
|
||||
input = coinlib.TaprootKeyInput(prevOut: prevOutpoint);
|
||||
|
||||
default:
|
||||
throw UnsupportedError(
|
||||
"Unknown derivation path type found: ${utxoSigningData[i].derivePathType}",
|
||||
);
|
||||
}
|
||||
|
||||
clTx = clTx.addInput(input);
|
||||
}
|
||||
|
||||
final String notificationAddress =
|
||||
targetPaymentCode.notificationAddressP2PKH();
|
||||
|
||||
txb.addOutput(
|
||||
notificationAddress,
|
||||
(overrideAmountForTesting ?? cryptoCurrency.dustLimitP2PKH.raw).toInt(),
|
||||
final address = coinlib.Address.fromString(
|
||||
normalizeAddress(notificationAddress),
|
||||
cryptoCurrency.networkParams,
|
||||
);
|
||||
|
||||
final output = coinlib.Output.fromAddress(
|
||||
overrideAmountForTesting ?? cryptoCurrency.dustLimitP2PKH.raw,
|
||||
address,
|
||||
);
|
||||
|
||||
clTx = clTx.addOutput(output);
|
||||
|
||||
clTx = clTx.addOutput(
|
||||
coinlib.Output.fromScriptBytes(
|
||||
BigInt.zero,
|
||||
opReturnScript,
|
||||
),
|
||||
);
|
||||
txb.addOutput(opReturnScript, 0);
|
||||
|
||||
// TODO: add possible change output and mark output as dangerous
|
||||
if (change > BigInt.zero) {
|
||||
// generate new change address if current change address has been used
|
||||
await checkChangeAddressForTransactions();
|
||||
final String changeAddress = (await getCurrentChangeAddress())!.value;
|
||||
txb.addOutput(changeAddress, change.toInt());
|
||||
|
||||
final output = coinlib.Output.fromAddress(
|
||||
change,
|
||||
coinlib.Address.fromString(
|
||||
normalizeAddress(changeAddress),
|
||||
cryptoCurrency.networkParams,
|
||||
),
|
||||
);
|
||||
|
||||
clTx = clTx.addOutput(output);
|
||||
}
|
||||
|
||||
txb.sign(
|
||||
vin: 0,
|
||||
keyPair: myKeyPair,
|
||||
witnessValue: utxo.value,
|
||||
witnessScript: utxoSigningData.first.redeemScript,
|
||||
clTx = clTx.sign(
|
||||
inputN: 0,
|
||||
value: BigInt.from(utxo.value),
|
||||
key: myKeyPair.privateKey,
|
||||
prevOuts: prevOuts,
|
||||
);
|
||||
|
||||
// sign rest of possible inputs
|
||||
for (var i = 1; i < utxoSigningData.length; i++) {
|
||||
txb.sign(
|
||||
vin: i,
|
||||
keyPair: utxoSigningData[i].keyPair!,
|
||||
witnessValue: utxoSigningData[i].utxo.value,
|
||||
witnessScript: utxoSigningData[i].redeemScript,
|
||||
for (int i = 1; i < utxoSigningData.length; i++) {
|
||||
final value = BigInt.from(utxoSigningData[i].utxo.value);
|
||||
coinlib.ECPrivateKey key = utxoSigningData[i].keyPair!.privateKey;
|
||||
|
||||
if (clTx.inputs[i] is coinlib.TaprootKeyInput) {
|
||||
final taproot = coinlib.Taproot(
|
||||
internalKey: utxoSigningData[i].keyPair!.publicKey,
|
||||
);
|
||||
|
||||
key = taproot.tweakPrivateKey(key);
|
||||
}
|
||||
|
||||
clTx = clTx.sign(
|
||||
inputN: i,
|
||||
value: value,
|
||||
key: key,
|
||||
prevOuts: prevOuts,
|
||||
);
|
||||
}
|
||||
|
||||
final builtTx = txb.build();
|
||||
|
||||
return Tuple2(builtTx.toHex(), builtTx.virtualSize());
|
||||
return Tuple2(clTx.toHex(), clTx.size);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"_createNotificationTx(): $e\n$s",
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2
|
|||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/models/signing_data.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/extensions/extensions.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
|
||||
|
@ -1001,13 +1002,64 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
for (final sd in setCoins) {
|
||||
vin.add(sd);
|
||||
|
||||
final pubKey = sd.keyPair!.publicKey.data;
|
||||
final btc.PaymentData? data;
|
||||
|
||||
switch (sd.derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
data = btc
|
||||
.P2PKH(
|
||||
data: btc.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip49:
|
||||
final p2wpkh = btc
|
||||
.P2WPKH(
|
||||
data: btc.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
data = btc
|
||||
.P2SH(
|
||||
data: btc.PaymentData(redeem: p2wpkh),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip84:
|
||||
data = btc
|
||||
.P2WPKH(
|
||||
data: btc.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip86:
|
||||
data = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
|
||||
// add to dummy tx
|
||||
dummyTxb.addInput(
|
||||
sd.utxo.txid,
|
||||
sd.utxo.vout,
|
||||
0xffffffff -
|
||||
1, // minus 1 is important. 0xffffffff on its own will burn funds
|
||||
sd.output,
|
||||
data!.output!,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1015,9 +1067,15 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
for (var i = 0; i < setCoins.length; i++) {
|
||||
dummyTxb.sign(
|
||||
vin: i,
|
||||
keyPair: setCoins[i].keyPair!,
|
||||
keyPair: btc.ECPair.fromPrivateKey(
|
||||
setCoins[i].keyPair!.privateKey.data,
|
||||
network: _bitcoinDartNetwork,
|
||||
compressed: setCoins[i].keyPair!.privateKey.compressed,
|
||||
),
|
||||
witnessValue: setCoins[i].utxo.value,
|
||||
redeemScript: setCoins[i].redeemScript,
|
||||
|
||||
// maybe not needed here as this was originally copied from btc? We'll find out...
|
||||
// redeemScript: setCoins[i].redeemScript,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1114,12 +1172,63 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
txb.setVersion(txVersion);
|
||||
txb.setLockTime(lockTime);
|
||||
for (final input in vin) {
|
||||
final pubKey = input.keyPair!.publicKey.data;
|
||||
final btc.PaymentData? data;
|
||||
|
||||
switch (input.derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
data = btc
|
||||
.P2PKH(
|
||||
data: btc.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip49:
|
||||
final p2wpkh = btc
|
||||
.P2WPKH(
|
||||
data: btc.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
data = btc
|
||||
.P2SH(
|
||||
data: btc.PaymentData(redeem: p2wpkh),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip84:
|
||||
data = btc
|
||||
.P2WPKH(
|
||||
data: btc.PaymentData(
|
||||
pubkey: pubKey,
|
||||
),
|
||||
network: _bitcoinDartNetwork,
|
||||
)
|
||||
.data;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip86:
|
||||
data = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
|
||||
txb.addInput(
|
||||
input.utxo.txid,
|
||||
input.utxo.vout,
|
||||
0xffffffff -
|
||||
1, // minus 1 is important. 0xffffffff on its own will burn funds
|
||||
input.output,
|
||||
data!.output!,
|
||||
);
|
||||
|
||||
tempInputs.add(
|
||||
|
@ -1172,9 +1281,15 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
|||
for (var i = 0; i < vin.length; i++) {
|
||||
txb.sign(
|
||||
vin: i,
|
||||
keyPair: vin[i].keyPair!,
|
||||
keyPair: btc.ECPair.fromPrivateKey(
|
||||
vin[i].keyPair!.privateKey.data,
|
||||
network: _bitcoinDartNetwork,
|
||||
compressed: vin[i].keyPair!.privateKey.compressed,
|
||||
),
|
||||
witnessValue: vin[i].utxo.value,
|
||||
redeemScript: vin[i].redeemScript,
|
||||
|
||||
// maybe not needed here as this was originally copied from btc? We'll find out...
|
||||
// redeemScript: setCoins[i].redeemScript,
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
|
|
Loading…
Reference in a new issue