mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-19 01:04:43 +00:00
wip
This commit is contained in:
parent
5ec0e264ce
commit
7b5c36e5a7
7 changed files with 185 additions and 128 deletions
|
@ -1,4 +1,6 @@
|
|||
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/utils.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
|
@ -7,88 +9,91 @@ import 'package:cw_mweb/cw_mweb.dart';
|
|||
import 'package:cw_mweb/mwebd.pb.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'package:bech32/bech32.dart';
|
||||
import 'package:r_crypto/r_crypto.dart';
|
||||
// import 'dart:typed_data';
|
||||
// import 'package:bech32/bech32.dart';
|
||||
// import 'package:r_crypto/r_crypto.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';
|
||||
|
||||
class Keychain {
|
||||
final ECPrivate scan;
|
||||
ECPrivate? spend;
|
||||
ECPublic? spendPubKey;
|
||||
// ECPrivate mi(int index) {
|
||||
// final input = BytesBuilder();
|
||||
|
||||
// // Write HashTagAddress to the input
|
||||
// input.addByte(HashTagAddress.codeUnitAt(0));
|
||||
|
||||
Keychain({required this.scan, this.spend, this.spendPubKey}) {
|
||||
if (this.spend != null) {
|
||||
spendPubKey = this.spend!.getPublic();
|
||||
}
|
||||
}
|
||||
// // 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);
|
||||
|
||||
static const HashTagAddress = 'A';
|
||||
// // Hash the input using Blake3 with a length of 32 bytes
|
||||
// final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
|
||||
|
||||
ECPrivate mi(int index) {
|
||||
final input = BytesBuilder();
|
||||
// // Return the hash digest
|
||||
// var res = Uint8List.fromList(hash);
|
||||
// return ECPrivate.fromBytes(res);
|
||||
// }
|
||||
|
||||
// Write HashTagAddress to the input
|
||||
input.addByte(HashTagAddress.codeUnitAt(0));
|
||||
// Keychain address(int index) {
|
||||
|
||||
// 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);
|
||||
// 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());
|
||||
|
||||
// Write scan to the input
|
||||
input.add(scan.prive.raw);
|
||||
// // 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());
|
||||
|
||||
// Hash the input using Blake3 with a length of 32 bytes
|
||||
final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
|
||||
// return Keychain(scan: AiPriv, spend: BiPriv);
|
||||
// }
|
||||
|
||||
// Return the hash digest
|
||||
var res = Uint8List.fromList(hash);
|
||||
return ECPrivate.fromBytes(res);
|
||||
}
|
||||
// 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);
|
||||
// }
|
||||
|
||||
Keychain address(int index) {
|
||||
// // 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);
|
||||
// // }
|
||||
|
||||
final miPub = this.mi(index).getPublic();
|
||||
final Bi = spendPubKey!.pubkeyAdd(miPub);
|
||||
final Ai = Bi.pubkeyMult(ECPublic.fromBytes(scan.toBytes()));
|
||||
// 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());
|
||||
// String encodeMwebAddress(List<int> scriptPubKey) {
|
||||
// return bech32.encode(Bech32("ltcmweb", scriptPubKey));
|
||||
// }
|
||||
// }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
|
||||
|
||||
abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
|
||||
LitecoinWalletAddressesBase(
|
||||
WalletInfo walletInfo, {
|
||||
|
@ -119,7 +124,6 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
List<String> mwebAddrs = [];
|
||||
List<String> oldMwebAddrs = [];
|
||||
|
||||
|
||||
Future<void> topUpMweb(int index) async {
|
||||
final stub = await CwMweb.stub();
|
||||
while (oldMwebAddrs.length - index < 1000) {
|
||||
|
@ -135,16 +139,19 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Keychain k = Keychain(scan: ECPrivate.fromBytes(scanSecret), spendPubKey: ECPublic.fromBytes(spendPubkey),);
|
||||
|
||||
// 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 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}");
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -40,6 +40,12 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
|
|||
server = null
|
||||
port = null
|
||||
result.success(null)
|
||||
} else if (call.method == "address") {
|
||||
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)
|
||||
result.success(res)
|
||||
} else {
|
||||
result.notImplemented()
|
||||
}
|
||||
|
|
|
@ -3,70 +3,90 @@ import UIKit
|
|||
import Mwebd
|
||||
|
||||
public class CwMwebPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "cw_mweb", binaryMessenger: registrar.messenger())
|
||||
let instance = CwMwebPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "cw_mweb", binaryMessenger: registrar.messenger())
|
||||
let instance = CwMwebPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
private static var server: MwebdServer?
|
||||
private static var port: Int = 0
|
||||
private static var dataDir: String?
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("iOS " + UIDevice.current.systemVersion)
|
||||
case "start":
|
||||
stopServer()
|
||||
let args = call.arguments as? [String: String]
|
||||
let dataDir = args?["dataDir"]
|
||||
CwMwebPlugin.dataDir = dataDir
|
||||
startServer(result: result)
|
||||
case "stop":
|
||||
stopServer()
|
||||
result(nil)
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
private static var server: MwebdServer?
|
||||
private static var port: Int = 0
|
||||
private static var dataDir: String?
|
||||
|
||||
private func startServer(result: @escaping FlutterResult) {
|
||||
if CwMwebPlugin.server == nil {
|
||||
var error: NSError?
|
||||
CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, "", &error)
|
||||
|
||||
if let server = CwMwebPlugin.server {
|
||||
do {
|
||||
print("Starting server...")
|
||||
try server.start(0, ret0_: &CwMwebPlugin.port)
|
||||
print("Server started successfully on port: \(CwMwebPlugin.port)")
|
||||
result(CwMwebPlugin.port)
|
||||
} catch let startError as NSError {
|
||||
print("Server Start Error: \(startError.localizedDescription)")
|
||||
result(FlutterError(code: "Server Start Error", message: startError.localizedDescription, details: nil))
|
||||
}
|
||||
} else if let error = error {
|
||||
print("Server Creation Error: \(error.localizedDescription)")
|
||||
result(FlutterError(code: "Server Creation Error", message: error.localizedDescription, details: nil))
|
||||
} else {
|
||||
print("Unknown Error: Failed to create server")
|
||||
result(FlutterError(code: "Unknown Error", message: "Failed to create server", details: nil))
|
||||
}
|
||||
} else {
|
||||
print("Server already running on port: \(CwMwebPlugin.port)")
|
||||
result(CwMwebPlugin.port)
|
||||
}
|
||||
}
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("iOS " + UIDevice.current.systemVersion)
|
||||
break
|
||||
case "start":
|
||||
stopServer()
|
||||
let args = call.arguments as? [String: String]
|
||||
let dataDir = args?["dataDir"]
|
||||
CwMwebPlugin.dataDir = dataDir
|
||||
startServer(result: result)
|
||||
break
|
||||
case "stop":
|
||||
stopServer()
|
||||
result(nil)
|
||||
break
|
||||
case "address":
|
||||
let args = call.arguments as? [String: String]
|
||||
let scanSecret = args?["scanSecret"]
|
||||
let spendPub = args?["spendPub"]
|
||||
let index = args?["index"]
|
||||
result(address(scanSecret, spendPub, index))
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func stopServer() {
|
||||
print("Stopping server")
|
||||
CwMwebPlugin.server?.stop()
|
||||
CwMwebPlugin.server = nil
|
||||
CwMwebPlugin.port = 0
|
||||
}
|
||||
private func startServer(result: @escaping FlutterResult) {
|
||||
if CwMwebPlugin.server == nil {
|
||||
var error: NSError?
|
||||
CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, "", &error)
|
||||
|
||||
deinit {
|
||||
stopServer()
|
||||
}
|
||||
if let server = CwMwebPlugin.server {
|
||||
do {
|
||||
print("Starting server...")
|
||||
try server.start(0, ret0_: &CwMwebPlugin.port)
|
||||
print("Server started successfully on port: \(CwMwebPlugin.port)")
|
||||
result(CwMwebPlugin.port)
|
||||
} catch let startError as NSError {
|
||||
print("Server Start Error: \(startError.localizedDescription)")
|
||||
result(FlutterError(code: "Server Start Error", message: startError.localizedDescription, details: nil))
|
||||
}
|
||||
} else if let error = error {
|
||||
print("Server Creation Error: \(error.localizedDescription)")
|
||||
result(FlutterError(code: "Server Creation Error", message: error.localizedDescription, details: nil))
|
||||
} else {
|
||||
print("Unknown Error: Failed to create server")
|
||||
result(FlutterError(code: "Unknown Error", message: "Failed to create server", details: nil))
|
||||
}
|
||||
} else {
|
||||
print("Server already running on port: \(CwMwebPlugin.port)")
|
||||
result(CwMwebPlugin.port)
|
||||
}
|
||||
}
|
||||
|
||||
private func stopServer() {
|
||||
print("Stopping server")
|
||||
CwMwebPlugin.server?.stop()
|
||||
CwMwebPlugin.server = nil
|
||||
CwMwebPlugin.port = 0
|
||||
}
|
||||
|
||||
private func address(_ scanSecret: String?, _ spendPub: String?, _ index: Int?) -> String? {
|
||||
guard let scanSecret = scanSecret, let spendPub = spendPub, let index = index else {
|
||||
print("Invalid arguments for address function")
|
||||
return nil
|
||||
}
|
||||
|
||||
return MwebdAddressIndex(scanSecret, spendPub, UInt32(index))
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopServer()
|
||||
}
|
||||
}
|
|
@ -53,6 +53,15 @@ class CwMweb {
|
|||
await cleanup();
|
||||
}
|
||||
|
||||
static Future<String?> address(String scanSecret, String spendPub, int index) async {
|
||||
// try {
|
||||
// return (await CwMwebPlatform.instance.address(scan, spendPub, index))!;
|
||||
// } catch (e) {
|
||||
// print("error generating address!: $e");
|
||||
// }
|
||||
return CwMwebPlatform.instance.address(scanSecret, spendPub, index);
|
||||
}
|
||||
|
||||
static Future<void> cleanup() async {
|
||||
await _clientChannel?.terminate();
|
||||
_rpcClient = null;
|
||||
|
|
|
@ -19,4 +19,14 @@ class MethodChannelCwMweb extends CwMwebPlatform {
|
|||
Future<void> stop() async {
|
||||
await methodChannel.invokeMethod<void>('stop');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> address(String scanSecret, String spendPub, int index) async {
|
||||
final result = await methodChannel.invokeMethod<String>('address', {
|
||||
'scanSecret': scanSecret,
|
||||
'spendPub': spendPub,
|
||||
'index': index,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,4 +30,8 @@ abstract class CwMwebPlatform extends PlatformInterface {
|
|||
Future<void> stop() {
|
||||
throw UnimplementedError('stop() has not been implemented.');
|
||||
}
|
||||
|
||||
Future<String?> address(String scanSecret, String spendPub, int index) {
|
||||
throw UnimplementedError('address(int) has not been implemented.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ dependency_overrides:
|
|||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_base
|
||||
ref: cake-update-v6
|
||||
ffi: 2.1.0
|
||||
|
||||
flutter_icons:
|
||||
image_path: "assets/images/app_logo.png"
|
||||
|
|
Loading…
Reference in a new issue