This commit is contained in:
julian 2024-05-09 11:56:42 -06:00
parent 9bfac51926
commit 12a0e4c289

View file

@ -192,7 +192,8 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
rawValue: BigInt.zero, rawValue: BigInt.zero,
fractionDigits: cryptoCurrency.fractionDigits, fractionDigits: cryptoCurrency.fractionDigits,
), ),
(p, e) => p + e); (p, e) => p + e,
);
// See SPARK_VALUE_SPEND_LIMIT_PER_TRANSACTION at https://github.com/firoorg/sparkmobile/blob/ef2e39aae18ecc49e0ddc63a3183e9764b96012e/include/spark.h#L17 // See SPARK_VALUE_SPEND_LIMIT_PER_TRANSACTION at https://github.com/firoorg/sparkmobile/blob/ef2e39aae18ecc49e0ddc63a3183e9764b96012e/include/spark.h#L17
// and COIN https://github.com/firoorg/sparkmobile/blob/ef2e39aae18ecc49e0ddc63a3183e9764b96012e/bitcoin/amount.h#L17 // and COIN https://github.com/firoorg/sparkmobile/blob/ef2e39aae18ecc49e0ddc63a3183e9764b96012e/bitcoin/amount.h#L17
@ -203,7 +204,8 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
fractionDigits: cryptoCurrency.fractionDigits, fractionDigits: cryptoCurrency.fractionDigits,
)) { )) {
throw Exception( throw Exception(
"Spend to transparent address limit exceeded (10,000 Firo per transaction)."); "Spend to transparent address limit exceeded (10,000 Firo per transaction).",
);
} }
final sparkSumOut = final sparkSumOut =
@ -212,7 +214,8 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
rawValue: BigInt.zero, rawValue: BigInt.zero,
fractionDigits: cryptoCurrency.fractionDigits, fractionDigits: cryptoCurrency.fractionDigits,
), ),
(p, e) => p + e); (p, e) => p + e,
);
final txAmount = transparentSumOut + sparkSumOut; final txAmount = transparentSumOut + sparkSumOut;
@ -239,12 +242,14 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
// prepare coin data for ffi // prepare coin data for ffi
final serializedCoins = coins final serializedCoins = coins
.map((e) => ( .map(
(e) => (
serializedCoin: e.serializedCoinB64!, serializedCoin: e.serializedCoinB64!,
serializedCoinContext: e.contextB64!, serializedCoinContext: e.contextB64!,
groupId: e.groupId, groupId: e.groupId,
height: e.height!, height: e.height!,
)) ),
)
.toList(); .toList();
final currentId = await electrumXClient.getSparkLatestCoinId(); final currentId = await electrumXClient.getSparkLatestCoinId();
@ -266,16 +271,20 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
} }
final allAnonymitySets = setMaps final allAnonymitySets = setMaps
.map((e) => ( .map(
(e) => (
setId: e["coinGroupID"] as int, setId: e["coinGroupID"] as int,
setHash: e["setHash"] as String, setHash: e["setHash"] as String,
set: (e["coins"] as List) set: (e["coins"] as List)
.map((e) => ( .map(
(e) => (
serializedCoin: e[0] as String, serializedCoin: e[0] as String,
txHash: e[1] as String, txHash: e[1] as String,
)) ),
)
.toList(), .toList(),
)) ),
)
.toList(); .toList();
final root = await getRootHDNode(); final root = await getRootHDNode();
@ -437,27 +446,32 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
privateKeyHex: privateKey.toHex, privateKeyHex: privateKey.toHex,
index: kDefaultSparkIndex, index: kDefaultSparkIndex,
recipients: txData.recipients recipients: txData.recipients
?.map((e) => ( ?.map(
(e) => (
address: e.address, address: e.address,
amount: e.amount.raw.toInt(), amount: e.amount.raw.toInt(),
subtractFeeFromAmount: isSendAll, subtractFeeFromAmount: isSendAll,
)) ),
)
.toList() ?? .toList() ??
[], [],
privateRecipients: txData.sparkRecipients privateRecipients: txData.sparkRecipients
?.map((e) => ( ?.map(
(e) => (
sparkAddress: e.address, sparkAddress: e.address,
amount: e.amount.raw.toInt(), amount: e.amount.raw.toInt(),
subtractFeeFromAmount: isSendAll, subtractFeeFromAmount: isSendAll,
memo: e.memo, memo: e.memo,
)) ),
)
.toList() ?? .toList() ??
[], [],
serializedCoins: serializedCoins, serializedCoins: serializedCoins,
allAnonymitySets: allAnonymitySets, allAnonymitySets: allAnonymitySets,
idAndBlockHashes: idAndBlockHashes idAndBlockHashes: idAndBlockHashes
.map( .map(
(e) => (setId: e.groupId, blockHash: base64Decode(e.blockHash))) (e) => (setId: e.groupId, blockHash: base64Decode(e.blockHash)),
)
.toList(), .toList(),
txHash: extractedTx.getHash(), txHash: extractedTx.getHash(),
), ),
@ -504,16 +518,20 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
for (final usedCoin in spend.usedCoins) { for (final usedCoin in spend.usedCoins) {
try { try {
usedSparkCoins.add(coins usedSparkCoins.add(
.firstWhere((e) => coins
.firstWhere(
(e) =>
usedCoin.height == e.height && usedCoin.height == e.height &&
usedCoin.groupId == e.groupId && usedCoin.groupId == e.groupId &&
base64Decode(e.serializedCoinB64!) base64Decode(e.serializedCoinB64!).toHex.startsWith(
.toHex base64Decode(usedCoin.serializedCoin).toHex,
.startsWith(base64Decode(usedCoin.serializedCoin).toHex)) ),
)
.copyWith( .copyWith(
isUsed: true, isUsed: true,
)); ),
);
} catch (_) { } catch (_) {
throw Exception( throw Exception(
"Unexpectedly did not find used spark coin. This should never happen.", "Unexpectedly did not find used spark coin. This should never happen.",
@ -576,8 +594,10 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
return await updateSentCachedTxData(txData: txData); return await updateSentCachedTxData(txData: txData);
} catch (e, s) { } catch (e, s) {
Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", Logging.instance.log(
level: LogLevel.Error); "Exception rethrown from confirmSend(): $e\n$s",
level: LogLevel.Error,
);
rethrow; rethrow;
} }
} }
@ -695,9 +715,11 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
); );
final spendable = Amount( final spendable = Amount(
rawValue: unusedCoins rawValue: unusedCoins
.where((e) => .where(
(e) =>
e.height != null && e.height != null &&
e.height! + cryptoCurrency.minConfirms <= currentHeight) e.height! + cryptoCurrency.minConfirms <= currentHeight,
)
.map((e) => e.value) .map((e) => e.value)
.fold(BigInt.zero, (prev, e) => prev + e), .fold(BigInt.zero, (prev, e) => prev + e),
fractionDigits: cryptoCurrency.fractionDigits, fractionDigits: cryptoCurrency.fractionDigits,
@ -802,7 +824,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
} }
// organise utxos // organise utxos
Map<String, List<UTXO>> utxosByAddress = {}; final Map<String, List<UTXO>> utxosByAddress = {};
for (final utxo in availableUtxos) { for (final utxo in availableUtxos) {
utxosByAddress[utxo.address!] ??= []; utxosByAddress[utxo.address!] ??= [];
utxosByAddress[utxo.address!]!.add(utxo); utxosByAddress[utxo.address!]!.add(utxo);
@ -811,7 +833,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
// setup some vars // setup some vars
int nChangePosInOut = -1; int nChangePosInOut = -1;
int nChangePosRequest = nChangePosInOut; final int nChangePosRequest = nChangePosInOut;
List<MutableSparkRecipient> outputs_ = outputs List<MutableSparkRecipient> outputs_ = outputs
.map((e) => MutableSparkRecipient(e.address, e.value, e.memo)) .map((e) => MutableSparkRecipient(e.address, e.value, e.memo))
.toList(); // deep copy .toList(); // deep copy
@ -934,11 +956,13 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
// Generate dummy mint coins to save time // Generate dummy mint coins to save time
final dummyRecipients = LibSpark.createSparkMintRecipients( final dummyRecipients = LibSpark.createSparkMintRecipients(
outputs: singleTxOutputs outputs: singleTxOutputs
.map((e) => ( .map(
(e) => (
sparkAddress: e.address, sparkAddress: e.address,
value: e.value.toInt(), value: e.value.toInt(),
memo: "", memo: "",
)) ),
)
.toList(), .toList(),
serialContext: Uint8List(0), serialContext: Uint8List(0),
generate: false, generate: false,
@ -952,11 +976,13 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
if (recipient.amount < cryptoCurrency.dustLimit.raw.toInt()) { if (recipient.amount < cryptoCurrency.dustLimit.raw.toInt()) {
throw Exception("Output amount too small"); throw Exception("Output amount too small");
} }
vout.add(( vout.add(
(
recipient.scriptPubKey, recipient.scriptPubKey,
recipient.amount, recipient.amount,
singleTxOutputs[i].address, singleTxOutputs[i].address,
)); ),
);
} }
// Choose coins to use // Choose coins to use
@ -973,7 +999,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
// priority stuff??? // priority stuff???
BigInt nChange = nValueIn - nValueToSelect; final BigInt nChange = nValueIn - nValueToSelect;
if (nChange > BigInt.zero) { if (nChange > BigInt.zero) {
if (nChange < cryptoCurrency.dustLimit.raw) { if (nChange < cryptoCurrency.dustLimit.raw) {
nChangePosInOut = -1; nChangePosInOut = -1;
@ -1106,10 +1132,12 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
// Generate real mint coins // Generate real mint coins
final serialContext = LibSpark.serializeMintContext( final serialContext = LibSpark.serializeMintContext(
inputs: setCoins inputs: setCoins
.map((e) => ( .map(
(e) => (
e.utxo.txid, e.utxo.txid,
e.utxo.vout, e.utxo.vout,
)) ),
)
.toList(), .toList(),
); );
final recipients = LibSpark.createSparkMintRecipients( final recipients = LibSpark.createSparkMintRecipients(
@ -1126,7 +1154,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
generate: true, generate: true,
); );
int i = 0; final int i = 0;
for (int i = 0; i < recipients.length; i++) { for (int i = 0; i < recipients.length; i++) {
final recipient = recipients[i]; final recipient = recipients[i];
final out = ( final out = (
@ -1267,9 +1295,11 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
.where() .where()
.walletIdEqualTo(walletId) .walletIdEqualTo(walletId)
.filter() .filter()
.valueEqualTo(addressOrScript is Uint8List .valueEqualTo(
addressOrScript is Uint8List
? output.$3! ? output.$3!
: addressOrScript as String) : addressOrScript as String,
)
.valueProperty() .valueProperty()
.findFirst()) != .findFirst()) !=
null, null,
@ -1646,12 +1676,7 @@ Future<
({ ({
String privateKeyHex, String privateKeyHex,
int index, int index,
List< List<({String address, int amount, bool subtractFeeFromAmount})> recipients,
({
String address,
int amount,
bool subtractFeeFromAmount
})> recipients,
List< List<
({ ({
String sparkAddress, String sparkAddress,
@ -1678,7 +1703,8 @@ Future<
Uint8List blockHash, Uint8List blockHash,
})> idAndBlockHashes, })> idAndBlockHashes,
Uint8List txHash, Uint8List txHash,
}) args) async { }) args,
) async {
final spend = LibSpark.createSparkSendTransaction( final spend = LibSpark.createSparkSendTransaction(
privateKeyHex: args.privateKeyHex, privateKeyHex: args.privateKeyHex,
index: args.index, index: args.index,
@ -1702,7 +1728,8 @@ Future<List<SparkCoin>> _identifyCoins(
Set<String> privateKeyHexSet, Set<String> privateKeyHexSet,
String walletId, String walletId,
bool isTestNet, bool isTestNet,
}) args) async { }) args,
) async {
final List<SparkCoin> myCoins = []; final List<SparkCoin> myCoins = [];
for (final privateKeyHex in args.privateKeyHexSet) { for (final privateKeyHex in args.privateKeyHexSet) {