This commit is contained in:
Matthew Fosse 2024-09-04 17:48:56 -07:00
parent 7b5c36e5a7
commit aa6cac897e
5 changed files with 54 additions and 98 deletions

View file

@ -4,6 +4,7 @@ import 'dart:io';
import 'dart:isolate';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cw_core/encryption_file_utils.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
@ -795,7 +796,10 @@ abstract class ElectrumWalletBase
throw BitcoinTransactionWrongBalanceException();
}
final changeAddress = await walletAddresses.getChangeAddress();
final changeAddress = await walletAddresses.getChangeAddress(
outputs: outputs,
utxoDetails: utxoDetails,
);
final address = addressTypeFromStr(changeAddress, network);
outputs.add(BitcoinOutput(
address: address,
@ -2061,7 +2065,8 @@ abstract class ElectrumWalletBase
_isTryingToConnect = true;
Timer(Duration(seconds: 10), () {
if (this.syncStatus is NotConnectedSyncStatus || this.syncStatus is LostConnectionSyncStatus) {
if (this.syncStatus is NotConnectedSyncStatus ||
this.syncStatus is LostConnectionSyncStatus) {
this.electrumClient.connectToUri(
node!.uri,
useSSL: node!.useSSL ?? false,
@ -2387,6 +2392,8 @@ class PublicKeyWithDerivationPath {
}
BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
// print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// print(network);
if (network is BitcoinCashNetwork) {
if (!address.startsWith("bitcoincash:") &&
(address.startsWith("q") || address.startsWith("p"))) {

View file

@ -1,6 +1,7 @@
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
@ -239,7 +240,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
@action
Future<String> getChangeAddress() async {
Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
updateChangeAddresses();
if (changeAddresses.isEmpty) {

View file

@ -2,6 +2,7 @@ import 'package:bech32/bech32.dart';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/bech32/bech32_base.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_bitcoin/utils.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart';
@ -15,79 +16,6 @@ import 'package:mobx/mobx.dart';
part 'litecoin_wallet_addresses.g.dart';
// class Keychain {
// // ECPrivate scan;
// // ECPrivate? spend;
// ECPrivate scan;
// ECPrivate? spend;
// ECPublic? spendPubKey;
// Keychain({required this.scan, this.spend, this.spendPubKey}) {
// if (this.spend != null) {
// spendPubKey = this.spend!.getPublic();
// }
// }
// static const HashTagAddress = 'A';
// ECPrivate mi(int index) {
// final input = BytesBuilder();
// // Write HashTagAddress to the input
// input.addByte(HashTagAddress.codeUnitAt(0));
// // Write index to the input in little endian
// final indexBytes = Uint8List(4);
// final byteData = ByteData.view(indexBytes.buffer);
// byteData.setUint32(0, index, Endian.little);
// input.add(indexBytes);
// // Write scan to the input
// input.add(scan.prive.raw);
// // Hash the input using Blake3 with a length of 32 bytes
// final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
// // Return the hash digest
// var res = Uint8List.fromList(hash);
// return ECPrivate.fromBytes(res);
// }
// Keychain address(int index) {
// final miPub = this.mi(index).getPublic();
// final Bi = spendPubKey!.pubkeyAdd(miPub);
// // final Ai = Bi.pubkeyMult(ECPublic.fromBytes(scan.toBytes()));
// final Ai = Bi.tweakMul(scan.toBigInt());
// // final miPubKey = ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
// // final Bi = spendPubKey + miPubKey;
// // return Uint8List.fromList(Ai.getEncoded(compressed: true) + Bi.getEncoded(compressed: true));
// final AiPriv = ECPrivate.fromBytes(Ai.toBytes());
// final BiPriv = ECPrivate.fromBytes(Bi.toBytes());
// return Keychain(scan: AiPriv, spend: BiPriv);
// }
// String addressString(int index) {
// final address = this.address(index);
// List<int> bytes = [];
// bytes.addAll(address.scan.toBytes());
// bytes.addAll(address.spend!.toBytes());
// return encodeMwebAddress(bytes);
// }
// // Uint8List spendKey(int index) {
// // final mi = this.mi(index);
// // final spendKey = spend + ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
// // return spendKey.getEncoded(compressed: true);
// // }
// String encodeMwebAddress(List<int> scriptPubKey) {
// return bech32.encode(Bech32("ltcmweb", scriptPubKey));
// }
// }
String encodeMwebAddress(List<int> scriptPubKey) {
return bech32.encode(Bech32("ltcmweb1", scriptPubKey), 250);
}
@ -126,32 +54,28 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
Future<void> topUpMweb(int index) async {
final stub = await CwMweb.stub();
while (oldMwebAddrs.length - index < 1000) {
final length = oldMwebAddrs.length;
while (mwebAddrs.length - index < 1000) {
final length = mwebAddrs.length;
final resp = await stub.addresses(AddressRequest(
fromIndex: length,
toIndex: index + 1000,
scanSecret: scanSecret,
spendPubkey: spendPubkey,
));
if (oldMwebAddrs.length == length) {
oldMwebAddrs.addAll(resp.address);
if (mwebAddrs.length == length) {
mwebAddrs.addAll(resp.address);
}
}
// Keychain k = Keychain(scan: ECPrivate.fromBytes(scanSecret), spendPubKey: ECPublic.fromBytes(spendPubkey),);
for (int i = 0; i < 10; i++) {
// final address = k.addressString(i + 1000);
final addressHex =
await CwMweb.address(hex.encode(scanSecret), hex.encode(spendPubkey), index);
// print(addressHex);
// print(hex.decode(addressHex!).length);
// return;
final address = encodeMwebAddress(hex.decode(addressHex!));
mwebAddrs.add(address);
}
print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
// for (int i = 0; i < 10; i++) {
// final address = await CwMweb.address(
// hex.encode(scanSecret),
// hex.encode(spendPubkey),
// index + 1000,
// );
// mwebAddrs.add(address!);
// }
// print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
}
@override
@ -185,11 +109,38 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
@action
@override
Future<String> getChangeAddress() async {
Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
// use regular change address on peg in, otherwise use mweb for change address:
if (outputs != null && utxoDetails != null) {
// check if this is a PEGIN:
bool outputsToMweb = false;
bool comesFromMweb = false;
for (var i = 0; i < outputs.length; i++) {
// TODO: probably not the best way to tell if this is an mweb address
// (but it doesn't contain the "mweb" text at this stage)
if (outputs[i].address.toAddress(network).length > 110) {
outputsToMweb = true;
}
}
utxoDetails.availableInputs.forEach((element) {
if (element.address.contains("mweb")) {
comesFromMweb = true;
}
});
bool isPegIn = !comesFromMweb && outputsToMweb;
if (isPegIn && mwebEnabled) {
return super.getChangeAddress();
}
}
if (mwebEnabled) {
await topUpMweb(0);
return mwebAddrs[0];
}
return super.getChangeAddress();
}
}

View file

@ -44,7 +44,6 @@ dependencies:
bech32:
git:
url: https://github.com/cake-tech/bech32.git
r_crypto: ^0.5.0
dev_dependencies:
flutter_test:

View file

@ -30,8 +30,6 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
if (call.method == "start") {
server?.stop()
val dataDir = call.argument("dataDir") ?: ""
// server = server ?: Mwebd.newServer("", dataDir, "")
// port = port ?: server?.start(0)
server = server ?: Mwebd.newServer("", dataDir, "")
port = server?.start(0)
result.success(port)
@ -44,7 +42,7 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
val scanSecret: String = call.argument<String>("scanSecret") ?: ""
val spendPub: String = call.argument<String>("spendPub") ?: ""
val index: Int = call.argument<Int>("index") ?: 0
val res = Mwebd.addressIndex(scanSecret, spendPub)
val res = Mwebd.addressIndex(scanSecret, spendPub, index.toString())
result.success(res)
} else {
result.notImplemented()