Unverified Commit 6b050c2f authored by Joseph Mark's avatar Joseph Mark Committed by GitHub
Browse files

feat: error handling/report in rust lib (#597)



* add error handling to remaining rust fns

* update swift functions and c api

* return exception message from java

* add helper function in android
Co-authored-by: Hanwen Cheng's avatarHanwen Cheng <heawen.cheng@gmail.com>
parent b92591e2
Pipeline #88692 failed with stages
in 4 minutes and 14 seconds
......@@ -30,6 +30,12 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
System.loadLibrary("signer");
}
private void rejectWithException(Promise promise, String code, Exception e) {
String[] sp = e.getMessage().split(": ");
String s = sp[sp.length - 1].trim().replace("\"", "");
promise.reject(code, s);
}
@Override
public String getName() {
return "EthkeyBridge";
......@@ -49,7 +55,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyBrainwalletBIP39Address(seed));
} catch (Exception e) {
promise.reject("invalid phrase", "invalid phrase");
rejectWithException(promise, "brainwallet bip39 address", e);
}
}
......@@ -58,7 +64,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyBrainwalletSign(seed, message));
} catch (Exception e) {
promise.reject("invalid phrase", "invalid phrase");
rejectWithException(promise, "brainwallet sign", e);
}
}
......@@ -67,8 +73,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyRlpItem(rlp, position));
} catch (Exception e) {
promise.reject("invalid rlp", "invalid rlp");
rejectWithException(promise, "rlp item", e);
}
}
......@@ -77,7 +82,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyKeccak(data));
} catch (Exception e) {
promise.reject("invalid data, expected hex-encoded string", "invalid data, expected hex-encoded string");
rejectWithException(promise, "keccak", e);
}
}
......@@ -86,7 +91,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyBlake(data));
} catch (Exception e) {
promise.reject("invalid data, expected hex-encoded string", "invalid data, expected hex-encoded string");
rejectWithException(promise, "blake2b", e);
}
}
......@@ -115,7 +120,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyDecryptData(data, password));
} catch (Exception e) {
promise.reject("invalid password", "invalid password");
rejectWithException(promise, "decrypt data", e);
}
}
......@@ -124,7 +129,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyQrCode(data));
} catch (Exception e) {
promise.reject("failed to create QR code", "failed to create QR code");
rejectWithException(promise, "qr code", e);
}
}
......@@ -133,7 +138,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(ethkeyQrCodeHex(data));
} catch (Exception e) {
promise.reject("failed to create QR code", "failed to create QR code");
rejectWithException(promise, "qr code hex", e);
}
}
......@@ -142,7 +147,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(substrateBrainwalletAddress(seed, prefix));
} catch (Exception e) {
promise.reject("invalid phrase", "invalid phrase");
rejectWithException(promise, "substrate address", e);
}
}
......@@ -151,7 +156,7 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(substrateBrainwalletSign(seed, message));
} catch (Exception e) {
promise.reject("invalid phrase", "invalid phrase");
rejectWithException(promise, "substrate sign", e);
}
}
......@@ -160,53 +165,53 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
try {
promise.resolve(schnorrkelVerify(seed, message, signature));
} catch (Exception e) {
promise.reject("invalid signature", "invalid signature");
}
}
@ReactMethod
public void decryptDataRef(String data, String password, Promise promise) {
try {
// `long` is incompatible with the bridge so pass as a double
double d = Double.longBitsToDouble(ethkeyDecryptDataRef(data, password));
if (Double.isNaN(d)) {
promise.reject("reference is nan", "reference is nan");
} else {
promise.resolve(d);
}
} catch (Exception e) {
promise.reject("decrypted ref", "decrypted ref");
}
}
@ReactMethod
public void destroyDataRef(double data_ref, Promise promise) {
try {
ethkeyDestroyDataRef(Double.doubleToRawLongBits(data_ref));
promise.resolve(0);
} catch (Exception e) {
promise.reject("destroy ref", "destroy ref");
}
}
@ReactMethod
public void brainWalletSignWithRef(double seed_ref, String message, Promise promise) {
try {
promise.resolve(ethkeyBrainwalletSignWithRef(Double.doubleToRawLongBits(seed_ref), message));
} catch (Exception e) {
promise.reject("invalid brain wallet phrase", "invalid brain wallet phrase");
}
}
@ReactMethod
public void substrateSignWithRef(double seed_ref, String suriSuffix, String message, Promise promise) {
try {
String s = ethkeySubstrateBrainwalletSignWithRef(Double.doubleToRawLongBits(seed_ref), suriSuffix, message);
promise.resolve(s);
} catch (Exception e) {
promise.reject("invalid substrate phrase", "invalid substrate phrase");
}
}
rejectWithException(promise, "schnorrkel verify", e);
}
}
@ReactMethod
public void decryptDataRef(String data, String password, Promise promise) {
try {
// `long` is incompatible with the bridge so pass as a double
double d = Double.longBitsToDouble(ethkeyDecryptDataRef(data, password));
if (Double.isNaN(d)) {
promise.reject("reference is nan", "reference is nan");
} else {
promise.resolve(d);
}
} catch (Exception e) {
rejectWithException(promise, "decrypt data ref", e);
}
}
@ReactMethod
public void destroyDataRef(double data_ref, Promise promise) {
try {
ethkeyDestroyDataRef(Double.doubleToRawLongBits(data_ref));
promise.resolve(0);
} catch (Exception e) {
rejectWithException(promise, "destroy data ref", e);
}
}
@ReactMethod
public void brainWalletSignWithRef(double seed_ref, String message, Promise promise) {
try {
promise.resolve(ethkeyBrainwalletSignWithRef(Double.doubleToRawLongBits(seed_ref), message));
} catch (Exception e) {
rejectWithException(promise, "brainwallet sign with ref", e);
}
}
@ReactMethod
public void substrateSignWithRef(double seed_ref, String suriSuffix, String message, Promise promise) {
try {
String s = ethkeySubstrateBrainwalletSignWithRef(Double.doubleToRawLongBits(seed_ref), suriSuffix, message);
promise.resolve(s);
} catch (Exception e) {
rejectWithException(promise, "substrate sign with ref", e);
}
}
@ReactMethod
public void brainWalletAddressWithRef(double seedRef, Promise promise) {
......@@ -214,17 +219,17 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
String s = ethkeyBrainWalletAddressWithRef(Double.doubleToRawLongBits(seedRef));
promise.resolve(s);
} catch (Exception e) {
promise.reject("invalid substrate phrase", "invalid substrate phrase");
rejectWithException(promise, "brainwallet address with ref", e);
}
}
@ReactMethod
@ReactMethod
public void substrateAddressWithRef(double seedRef, String suriSuffix, int prefix, Promise promise) {
try {
String substrateAddress = ethkeySubstrateWalletAddressWithRef(Double.doubleToRawLongBits(seedRef), suriSuffix, prefix);
promise.resolve(substrateAddress);
} catch (Exception e) {
promise.reject("invalid suri suffix or prefix", "invalid suri suffix or prefix");
rejectWithException(promise, "substrate address with ref", e);
}
}
......
This diff is collapsed.
......@@ -8,276 +8,272 @@
import Foundation
func handle_error<T, U>(
resolve: RCTPromiseResolveBlock,
reject: RCTPromiseRejectBlock,
get_result: (UnsafeMutablePointer<ExternError>) -> T,
success: (T) -> U
) -> Void {
var err = ExternError()
let err_ptr: UnsafeMutablePointer<ExternError> = UnsafeMutablePointer(&err)
let res = get_result(err_ptr)
if err_ptr.pointee.code == 0 {
resolve(success(res))
} else {
let val = String(cString: err_ptr.pointee.message)
signer_destroy_string(err_ptr.pointee.message)
reject(String(describing: err_ptr.pointee.code), val, nil)
}
}
@objc(EthkeyBridge)
class EthkeyBridge: NSObject {
public static func requiresMainQueueSetup() -> Bool {
return true;
}
@objc func brainWalletAddress(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var seed_ptr = seed.asPtr()
let address_rust_str = ethkey_brainwallet_address(&error, &seed_ptr)
let address_rust_str_ptr = rust_string_ptr(address_rust_str)
let address = String.fromStringPtr(ptr: address_rust_str_ptr!.pointee)
rust_string_ptr_destroy(address_rust_str_ptr)
rust_string_destroy(address_rust_str)
resolve(address)
handle_error(
resolve: resolve,
reject: reject,
get_result: { ethkey_brainwallet_address($0, seed) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func brainWalletSign(_ seed: String, message: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var seed_ptr = seed.asPtr()
var message_ptr = message.asPtr()
let signature_rust_str = ethkey_brainwallet_sign(&error, &seed_ptr, &message_ptr)
let signature_rust_str_ptr = rust_string_ptr(signature_rust_str)
let signature = String.fromStringPtr(ptr: signature_rust_str_ptr!.pointee)
rust_string_ptr_destroy(signature_rust_str_ptr)
rust_string_destroy(signature_rust_str)
resolve(signature)
handle_error(
resolve: resolve,
reject: reject,
get_result: { ethkey_brainwallet_sign($0, seed, message) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func rlpItem(_ rlp: String, position: UInt32, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var rlp_ptr = rlp.asPtr()
let item_rust_str = rlp_item(&error, &rlp_ptr, position)
let item_rust_str_ptr = rust_string_ptr(item_rust_str)
let item = String.fromStringPtr(ptr: item_rust_str_ptr!.pointee)
rust_string_ptr_destroy(item_rust_str_ptr)
rust_string_destroy(item_rust_str)
if (error == 0) {
resolve(item)
} else {
reject("invalid rlp", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { rlp_item($0, rlp, position) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func keccak(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
let hash_rust_str = keccak256(&error, &data_ptr)
let hash_rust_str_ptr = rust_string_ptr(hash_rust_str)
let hash = String.fromStringPtr(ptr: hash_rust_str_ptr!.pointee)
rust_string_ptr_destroy(hash_rust_str_ptr)
rust_string_destroy(hash_rust_str)
if (error == 0) {
resolve(hash)
} else {
reject("invalid data, expected hex-encoded string", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { keccak256($0, data) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func blake2b(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
let hash_rust_str = blake(&error, &data_ptr)
let hash_rust_str_ptr = rust_string_ptr(hash_rust_str)
let hash = String.fromStringPtr(ptr: hash_rust_str_ptr!.pointee)
rust_string_ptr_destroy(hash_rust_str_ptr)
rust_string_destroy(hash_rust_str)
if (error == 0) {
resolve(hash)
} else {
reject("invalid data, expected hex-encoded string", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { blake($0, data) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func ethSign(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
let hash_rust_str = eth_sign(&error, &data_ptr)
let hash_rust_str_ptr = rust_string_ptr(hash_rust_str)
let hash = String.fromStringPtr(ptr: hash_rust_str_ptr!.pointee)
rust_string_ptr_destroy(hash_rust_str_ptr)
rust_string_destroy(hash_rust_str)
resolve(hash)
handle_error(
resolve: resolve,
reject: reject,
get_result: { eth_sign($0, data) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func blockiesIcon(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var seed_ptr = seed.asPtr()
let icon_rust_str = blockies_icon(&error, &seed_ptr)
let icon_rust_str_ptr = rust_string_ptr(icon_rust_str)
let icon = String.fromStringPtr(ptr: icon_rust_str_ptr!.pointee)
rust_string_ptr_destroy(icon_rust_str_ptr)
rust_string_destroy(icon_rust_str)
if error == 0 {
resolve(icon)
} else {
reject("Failed to generate blockies", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { blockies_icon($0, seed) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func randomPhrase(_ wordsNumber:NSInteger, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
let words_number: Int32 = Int32(wordsNumber)
let words_rust_str = random_phrase(&error, words_number)
let words_rust_str_ptr = rust_string_ptr(words_rust_str)
let words = String.fromStringPtr(ptr: words_rust_str_ptr!.pointee)
rust_string_ptr_destroy(words_rust_str_ptr)
rust_string_destroy(words_rust_str)
resolve(words)
handle_error(
resolve: resolve,
reject: reject,
get_result: { random_phrase($0, Int32(wordsNumber)) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func encryptData(_ data: String, password: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
var password_ptr = password.asPtr()
let encrypted_data_rust_str = encrypt_data(&error, &data_ptr, &password_ptr)
let encrypted_data_rust_str_ptr = rust_string_ptr(encrypted_data_rust_str)
let encrypted_data = String.fromStringPtr(ptr: encrypted_data_rust_str_ptr!.pointee)
rust_string_ptr_destroy(encrypted_data_rust_str_ptr)
rust_string_destroy(encrypted_data_rust_str)
resolve(encrypted_data)
handle_error(
resolve: resolve,
reject: reject,
get_result: { encrypt_data($0, data, password) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func decryptData(_ data: String, password: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
var password_ptr = password.asPtr()
let decrypted_data_rust_str = decrypt_data(&error, &data_ptr, &password_ptr)
let decrypted_data_rust_str_ptr = rust_string_ptr(decrypted_data_rust_str)
let decrypted_data = String.fromStringPtr(ptr: decrypted_data_rust_str_ptr!.pointee)
rust_string_ptr_destroy(decrypted_data_rust_str_ptr)
rust_string_destroy(decrypted_data_rust_str)
if error == 0 {
resolve(decrypted_data)
} else {
reject("invalid password", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { decrypt_data($0, data, password) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func qrCode(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
let icon_rust_str = qrcode(&error, &data_ptr)
let icon_rust_str_ptr = rust_string_ptr(icon_rust_str)
let icon = String.fromStringPtr(ptr: icon_rust_str_ptr!.pointee)
rust_string_ptr_destroy(icon_rust_str_ptr)
rust_string_destroy(icon_rust_str)
if error == 0 {
resolve(icon)
} else {
reject("Failed to generate blockies", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { qrcode($0, data) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func qrCodeHex(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var data_ptr = data.asPtr()
let icon_rust_str = qrcode_hex(&error, &data_ptr)
let icon_rust_str_ptr = rust_string_ptr(icon_rust_str)
let icon = String.fromStringPtr(ptr: icon_rust_str_ptr!.pointee)
rust_string_ptr_destroy(icon_rust_str_ptr)
rust_string_destroy(icon_rust_str)
if error == 0 {
resolve(icon)
} else {
reject("Failed to generate blockies", nil, nil)
}
handle_error(
resolve: resolve,
reject: reject,
get_result: { qrcode_hex($0, data) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func substrateAddress(_ seed: String, prefix: UInt32, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var seed_ptr = seed.asPtr()
let address_rust_str = substrate_brainwallet_address(&error, &seed_ptr, prefix)
let address_rust_str_ptr = rust_string_ptr(address_rust_str)
let address = String.fromStringPtr(ptr: address_rust_str_ptr!.pointee)
rust_string_ptr_destroy(address_rust_str_ptr)
rust_string_destroy(address_rust_str)
resolve(address)
handle_error(
resolve: resolve,
reject: reject,
get_result: { substrate_brainwallet_address($0, seed, prefix) },
success: { (res: Optional<UnsafePointer<CChar>>) -> String in
let val = String(cString: res!)
signer_destroy_string(res!)
return val
})
}
@objc func substrateSign(_ seed: String, message: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var error: UInt32 = 0
var seed_ptr = seed.asPtr()
var message_ptr = message.asPtr()
let signature_rust_str = substrate_brainwallet_sign(&error, &seed_ptr, &message_ptr)
let signature_rust_str_ptr = rust_string_ptr(signature_rust_str)
let signature = String.fromStringPtr(ptr: signature_rust_str_ptr!.pointee)
rust_string_ptr_destroy(signature_rust_str_ptr)
rust_string_destroy(signature_rust_str)