From adadcbc982cdbae52b4c796b64909083d9305001 Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Sat, 3 Jul 2021 20:40:08 -0700 Subject: [PATCH] Return FfiResult errors as FfiError enum short values --- .../bdk/{JnaError.kt => FfiError.kt} | 3 +- .../org/bitcoindevkit/bdk/FfiException.kt | 14 ++ .../org/bitcoindevkit/bdk/JnaException.kt | 3 - .../kotlin/org/bitcoindevkit/bdk/LibJna.kt | 16 +- .../bitcoindevkit/bdk/types/StringResult.kt | 8 +- .../org/bitcoindevkit/bdk/types/VoidResult.kt | 8 +- .../bdk/wallet/VecLocalUtxoResult.kt | 8 +- .../bitcoindevkit/bdk/wallet/WalletResult.kt | 8 +- .../kotlin/org/bitcoindevkit/bdk/LibTest.kt | 4 +- cc/bdk_ffi.h | 171 +++++++++++++----- cc/bdk_ffi_test.c | 25 +-- src/error.rs | 134 +++++++++----- src/types.rs | 5 +- src/wallet/mod.rs | 18 +- 14 files changed, 281 insertions(+), 144 deletions(-) rename bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/{JnaError.kt => FfiError.kt} (96%) create mode 100644 bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiException.kt delete mode 100644 bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaException.kt diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaError.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiError.kt similarity index 96% rename from bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaError.kt rename to bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiError.kt index 32dcd5a..d5738f9 100644 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaError.kt +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiError.kt @@ -1,6 +1,7 @@ package org.bitcoindevkit.bdk -enum class JnaError { +enum class FfiError { + None, InvalidU32Bytes, Generic, ScriptDoesntHaveAddressForm, diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiException.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiException.kt new file mode 100644 index 0000000..5fd6ba8 --- /dev/null +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/FfiException.kt @@ -0,0 +1,14 @@ +package org.bitcoindevkit.bdk + +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +class FfiException(val err: FfiError) : Exception() { + private val log: Logger = LoggerFactory.getLogger(FfiException::class.java) + + init { + log.error("JnaError: [{}] {}",err.ordinal, err.name) + } + + internal constructor(err: Short) : this(FfiError.values()[err.toInt()]) +} \ No newline at end of file diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaException.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaException.kt deleted file mode 100644 index 6ce9768..0000000 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/JnaException.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.bitcoindevkit.bdk - -class JnaException internal constructor(val err: JnaError) : Exception() \ No newline at end of file diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/LibJna.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/LibJna.kt index f31d346..ffc36db 100644 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/LibJna.kt +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/LibJna.kt @@ -8,7 +8,7 @@ interface LibJna : Library { // // char * ok; // - // char * err; + // FfiError_t err; // //} FfiResult_char_ptr_t; open class FfiResult_char_ptr_t : Structure() { @@ -19,7 +19,7 @@ interface LibJna : Library { var ok: String = "" @JvmField - var err: String = "" + var err: Short = 0 override fun getFieldOrder() = listOf("ok", "err") } @@ -30,7 +30,7 @@ interface LibJna : Library { // typedef struct { // - // char * err; + // FfiError_t err; // //} FfiResultVoid_t; open class FfiResultVoid_t : Structure() { @@ -38,7 +38,7 @@ interface LibJna : Library { class ByReference : FfiResultVoid_t(), Structure.ByReference @JvmField - var err: String = "" + var err: Short = 0 override fun getFieldOrder() = listOf("err") } @@ -89,7 +89,7 @@ interface LibJna : Library { // // OpaqueWallet_t * ok; // - // char * err; + // FfiError_t err; // // } FfiResult_OpaqueWallet_ptr_t; open class FfiResult_OpaqueWallet_ptr_t : Structure() { @@ -100,7 +100,7 @@ interface LibJna : Library { var ok: OpaqueWallet_t = OpaqueWallet_t() @JvmField - var err: String = "" + var err: Short = 0 override fun getFieldOrder() = listOf("ok", "err") } @@ -215,7 +215,7 @@ interface LibJna : Library { // // Vec_LocalUtxo_t ok; // - // char * err; + // FfiError_t err; // // } FfiResult_Vec_LocalUtxo_t; open class FfiResultVec_LocalUtxo_t : Structure() { @@ -227,7 +227,7 @@ interface LibJna : Library { var ok: Vec_LocalUtxo_t = Vec_LocalUtxo_t() @JvmField - var err: String = "" + var err: Short = 0 override fun getFieldOrder() = listOf("ok", "err") } diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/StringResult.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/StringResult.kt index 2b5b35e..37d86a7 100644 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/StringResult.kt +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/StringResult.kt @@ -1,7 +1,6 @@ package org.bitcoindevkit.bdk.types -import org.bitcoindevkit.bdk.JnaError -import org.bitcoindevkit.bdk.JnaException +import org.bitcoindevkit.bdk.FfiException import org.bitcoindevkit.bdk.LibBase import org.bitcoindevkit.bdk.LibJna import org.slf4j.Logger @@ -16,9 +15,8 @@ class StringResult constructor(private val ffiResultCharPtrT: LibJna.FfiResult_c val err = ffiResultCharPtrT.err val ok = ffiResultCharPtrT.ok when { - err.isNotEmpty() -> { - log.error("JnaError: $err") - throw JnaException(JnaError.valueOf(err)) + err > 0 -> { + throw FfiException(err) } else -> { return ok diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/VoidResult.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/VoidResult.kt index 66071d9..6b9b685 100644 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/VoidResult.kt +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/types/VoidResult.kt @@ -1,7 +1,6 @@ package org.bitcoindevkit.bdk.types -import org.bitcoindevkit.bdk.JnaError -import org.bitcoindevkit.bdk.JnaException +import org.bitcoindevkit.bdk.FfiException import org.bitcoindevkit.bdk.LibBase import org.bitcoindevkit.bdk.LibJna import org.slf4j.Logger @@ -16,9 +15,8 @@ class VoidResult constructor(private val ffiResultVoidT: LibJna.FfiResultVoid_t. val err = ffiResultVoidT.err when { - err.isNotEmpty() -> { - log.error("JnaError: $err") - throw JnaException(JnaError.valueOf(err)) + err > 0 -> { + throw FfiException(err) } else -> { return diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/VecLocalUtxoResult.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/VecLocalUtxoResult.kt index 86564ef..c569c49 100644 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/VecLocalUtxoResult.kt +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/VecLocalUtxoResult.kt @@ -1,7 +1,6 @@ package org.bitcoindevkit.bdk.wallet -import org.bitcoindevkit.bdk.JnaError -import org.bitcoindevkit.bdk.JnaException +import org.bitcoindevkit.bdk.FfiException import org.bitcoindevkit.bdk.LibBase import org.bitcoindevkit.bdk.LibJna import org.slf4j.Logger @@ -16,9 +15,8 @@ class VecLocalUtxoResult(private val ffiResultVecLocalUtxoT: LibJna.FfiResultVec val err = ffiResultVecLocalUtxoT.err val ok = ffiResultVecLocalUtxoT.ok when { - err .isNotEmpty() -> { - log.error("JnaError: $err") - throw JnaException(JnaError.valueOf(err)) + err > 0 -> { + throw FfiException(err) } else -> { val first = ok.ptr!! diff --git a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/WalletResult.kt b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/WalletResult.kt index 52592ae..2d43b0c 100644 --- a/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/WalletResult.kt +++ b/bdk-kotlin/jvm/src/main/kotlin/org/bitcoindevkit/bdk/wallet/WalletResult.kt @@ -1,7 +1,6 @@ package org.bitcoindevkit.bdk.wallet -import org.bitcoindevkit.bdk.JnaError -import org.bitcoindevkit.bdk.JnaException +import org.bitcoindevkit.bdk.FfiException import org.bitcoindevkit.bdk.LibBase import org.bitcoindevkit.bdk.LibJna import org.slf4j.Logger @@ -16,9 +15,8 @@ class WalletResult constructor(private val ffiResultOpaqueWalletPtrT: LibJna.Ffi val err = ffiResultOpaqueWalletPtrT.err val ok = ffiResultOpaqueWalletPtrT.ok when { - err.isNotEmpty() -> { - log.error("JnaError: $err") - throw JnaException(JnaError.valueOf(err)) + err > 0 -> { + throw FfiException(err) } else -> { return ok diff --git a/bdk-kotlin/test-fixtures/src/main/kotlin/org/bitcoindevkit/bdk/LibTest.kt b/bdk-kotlin/test-fixtures/src/main/kotlin/org/bitcoindevkit/bdk/LibTest.kt index cf943b9..79d99d0 100644 --- a/bdk-kotlin/test-fixtures/src/main/kotlin/org/bitcoindevkit/bdk/LibTest.kt +++ b/bdk-kotlin/test-fixtures/src/main/kotlin/org/bitcoindevkit/bdk/LibTest.kt @@ -31,10 +31,10 @@ abstract class LibTest : LibBase() { @Test fun walletResultError() { - val jnaException = assertThrows(JnaException::class.java) { + val jnaException = assertThrows(FfiException::class.java) { Wallet("bad", "bad", blockchainConfig, databaseConfig) } - assertEquals(jnaException.err, JnaError.Descriptor) + assertEquals(jnaException.err, FfiError.Descriptor) } // @Test diff --git a/cc/bdk_ffi.h b/cc/bdk_ffi.h index 058fe82..3832f3e 100644 --- a/cc/bdk_ffi.h +++ b/cc/bdk_ffi.h @@ -14,8 +14,136 @@ extern "C" { #endif + +#include +#include + +/** \remark Has the same ABI as `uint16_t` **/ +#ifdef DOXYGEN +typedef enum FfiError +#else +typedef uint16_t FfiError_t; enum +#endif +{ + /** . */ + FFI_ERROR_NONE, + /** . */ + FFI_ERROR_INVALID_U32_BYTES, + /** . */ + FFI_ERROR_GENERIC, + /** . */ + FFI_ERROR_SCRIPT_DOESNT_HAVE_ADDRESS_FORM, + /** . */ + FFI_ERROR_SINGLE_RECIPIENT_MULTIPLE_OUTPUTS, + /** . */ + FFI_ERROR_SINGLE_RECIPIENT_NO_INPUTS, + /** . */ + FFI_ERROR_NO_RECIPIENTS, + /** . */ + FFI_ERROR_NO_UTXOS_SELECTED, + /** . */ + FFI_ERROR_OUTPUT_BELOW_DUST_LIMIT, + /** . */ + FFI_ERROR_INSUFFICIENT_FUNDS, + /** . */ + FFI_ERROR_BN_B_TOTAL_TRIES_EXCEEDED, + /** . */ + FFI_ERROR_BN_B_NO_EXACT_MATCH, + /** . */ + FFI_ERROR_UNKNOWN_UTXO, + /** . */ + FFI_ERROR_TRANSACTION_NOT_FOUND, + /** . */ + FFI_ERROR_TRANSACTION_CONFIRMED, + /** . */ + FFI_ERROR_IRREPLACEABLE_TRANSACTION, + /** . */ + FFI_ERROR_FEE_RATE_TOO_LOW, + /** . */ + FFI_ERROR_FEE_TOO_LOW, + /** . */ + FFI_ERROR_MISSING_KEY_ORIGIN, + /** . */ + FFI_ERROR_KEY, + /** . */ + FFI_ERROR_CHECKSUM_MISMATCH, + /** . */ + FFI_ERROR_SPENDING_POLICY_REQUIRED, + /** . */ + FFI_ERROR_INVALID_POLICY_PATH_ERROR, + /** . */ + FFI_ERROR_SIGNER, + /** . */ + FFI_ERROR_INVALID_PROGRESS_VALUE, + /** . */ + FFI_ERROR_PROGRESS_UPDATE_ERROR, + /** . */ + FFI_ERROR_INVALID_OUTPOINT, + /** . */ + FFI_ERROR_DESCRIPTOR, + /** . */ + FFI_ERROR_ADDRESS_VALIDATOR, + /** . */ + FFI_ERROR_ENCODE, + /** . */ + FFI_ERROR_MINISCRIPT, + /** . */ + FFI_ERROR_BIP32, + /** . */ + FFI_ERROR_SECP256K1, + /** . */ + FFI_ERROR_JSON, + /** . */ + FFI_ERROR_HEX, + /** . */ + FFI_ERROR_PSBT, + /** . */ + FFI_ERROR_ELECTRUM, + /** . */ + FFI_ERROR_SLED, +} +#ifdef DOXYGEN +FfiError_t +#endif +; + +typedef struct { + + char * ok; + + FfiError_t err; + +} FfiResult_char_ptr_t; + +void free_string_result ( + FfiResult_char_ptr_t string_result); + +typedef struct { + + FfiError_t err; + +} FfiResultVoid_t; + +void free_void_result ( + FfiResultVoid_t void_result); + +/** \brief + * Free a Rust-allocated string + */ +void free_string ( + char * string); + typedef struct BlockchainConfig BlockchainConfig_t; +BlockchainConfig_t * new_electrum_config ( + char const * url, + char const * socks5, + int16_t retry, + int16_t timeout); + +void free_blockchain_config ( + BlockchainConfig_t * blockchain_config); + typedef struct DatabaseConfig DatabaseConfig_t; typedef struct OpaqueWallet OpaqueWallet_t; @@ -24,7 +152,7 @@ typedef struct { OpaqueWallet_t * ok; - char * err; + FfiError_t err; } FfiResult_OpaqueWallet_ptr_t; @@ -37,30 +165,12 @@ FfiResult_OpaqueWallet_ptr_t new_wallet_result ( void free_wallet_result ( FfiResult_OpaqueWallet_ptr_t wallet_result); -typedef struct { - - char * err; - -} FfiResultVoid_t; - FfiResultVoid_t sync_wallet ( OpaqueWallet_t const * opaque_wallet); -typedef struct { - - char * ok; - - char * err; - -} FfiResult_char_ptr_t; - FfiResult_char_ptr_t new_address ( OpaqueWallet_t const * opaque_wallet); - -#include -#include - typedef struct { char * txid; @@ -104,7 +214,7 @@ typedef struct { Vec_LocalUtxo_t ok; - char * err; + FfiError_t err; } FfiResult_Vec_LocalUtxo_t; @@ -114,15 +224,6 @@ FfiResult_Vec_LocalUtxo_t list_unspent ( void free_unspent_result ( FfiResult_Vec_LocalUtxo_t unspent_result); -BlockchainConfig_t * new_electrum_config ( - char const * url, - char const * socks5, - int16_t retry, - int16_t timeout); - -void free_blockchain_config ( - BlockchainConfig_t * blockchain_config); - DatabaseConfig_t * new_memory_config (void); DatabaseConfig_t * new_sled_config ( @@ -132,18 +233,6 @@ DatabaseConfig_t * new_sled_config ( void free_database_config ( DatabaseConfig_t * database_config); -void free_string_result ( - FfiResult_char_ptr_t string_result); - -void free_void_result ( - FfiResultVoid_t void_result); - -/** \brief - * Free a Rust-allocated string - */ -void free_string ( - char * string); - #ifdef __cplusplus } /* extern "C" */ diff --git a/cc/bdk_ffi_test.c b/cc/bdk_ffi_test.c index 99744ce..fb6674a 100644 --- a/cc/bdk_ffi_test.c +++ b/cc/bdk_ffi_test.c @@ -14,16 +14,11 @@ int main (int argc, char const * const argv[]) // new wallet with bad descriptor FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result("bad","bad",bc_config,db_config); - assert(strlen(wallet_result.err) > 0); + assert(wallet_result.err == FFI_ERROR_DESCRIPTOR); assert(wallet_result.ok == NULL); free_blockchain_config(bc_config); - free_database_config(db_config); - - char *wallet_err = wallet_result.err; - assert(wallet_err != NULL); - assert( 0 == strcmp(wallet_err,"Descriptor") ); - // printf("wallet err: %s\n", wallet_err); + free_database_config(db_config); free_wallet_result(wallet_result); } @@ -38,8 +33,8 @@ int main (int argc, char const * const argv[]) // new wallet FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result(desc,change,bc_config,db_config); - // printf("wallet_result.err = %ld\n", strlen(wallet_result.err)); - assert(strlen(wallet_result.err) == 0); + // printf("wallet_result.err = %d\n", wallet_result.err)); + assert(wallet_result.err == FFI_ERROR_NONE); assert(wallet_result.ok != NULL); free_blockchain_config(bc_config); @@ -49,20 +44,20 @@ int main (int argc, char const * const argv[]) // sync wallet FfiResultVoid_t sync_result = sync_wallet(wallet); - assert(strlen(sync_result.err) == 0); + assert(sync_result.err == FFI_ERROR_NONE); free_void_result(sync_result); // new address FfiResult_char_ptr_t address1_result = new_address(wallet); assert(address1_result.ok != NULL); - assert(strlen(address1_result.err) == 0); + assert(address1_result.err == FFI_ERROR_NONE); // printf("address1 = %s\n", *address1_result.ok); assert( 0 == strcmp(address1_result.ok,"tb1qgkhp034fyxeta00h0nne9tzfm0vsxq4prduzxp")); free_string_result(address1_result); FfiResult_char_ptr_t address2_result = new_address(wallet); assert(address2_result.ok != NULL); - assert(strlen(address2_result.err) == 0); + assert(address2_result.err == FFI_ERROR_NONE); // printf("address2 = %s\n", *address2_result.ok); assert( 0 == strcmp(address2_result.ok,"tb1qd6u9q327sru2ljvwzdtfrdg36sapax7udz97wf")); free_string_result(address2_result); @@ -87,7 +82,7 @@ int main (int argc, char const * const argv[]) // new wallet FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result(desc,change,bc_config,db_config); - assert(strlen(wallet_result.err) == 0); + assert(wallet_result.err == FFI_ERROR_NONE); assert(wallet_result.ok != NULL); free_blockchain_config(bc_config); @@ -97,13 +92,13 @@ int main (int argc, char const * const argv[]) // sync wallet FfiResultVoid_t sync_result = sync_wallet(wallet); - assert(strlen(sync_result.err) == 0); + assert(sync_result.err == FFI_ERROR_NONE); free_void_result(sync_result); // list unspent FfiResult_Vec_LocalUtxo_t unspent_result = list_unspent(wallet); assert(unspent_result.ok.len == 7); - assert(strlen(unspent_result.err) == 0); + assert(unspent_result.err == FFI_ERROR_NONE); LocalUtxo_t * unspent_ptr = unspent_result.ok.ptr; for (int i = 0; i < unspent_result.ok.len; i++) { diff --git a/src/error.rs b/src/error.rs index 6af73f0..f27c6dd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,46 +1,94 @@ +use ::safer_ffi::prelude::*; use bdk::Error; -pub fn get_name(error: &bdk::Error) -> String { - match error { - Error::InvalidU32Bytes(_) => "InvalidU32Bytes", - Error::Generic(_) => "Generic", - Error::ScriptDoesntHaveAddressForm => "ScriptDoesntHaveAddressForm", - Error::SingleRecipientMultipleOutputs => "SingleRecipientMultipleOutputs", - Error::SingleRecipientNoInputs => "SingleRecipientNoInputs", - Error::NoRecipients => "NoRecipients", - Error::NoUtxosSelected => "NoUtxosSelected", - Error::OutputBelowDustLimit(_) => "OutputBelowDustLimit", - Error::InsufficientFunds { .. } => "InsufficientFunds", - Error::BnBTotalTriesExceeded => "BnBTotalTriesExceeded", - Error::BnBNoExactMatch => "BnBNoExactMatch", - Error::UnknownUtxo => "UnknownUtxo", - Error::TransactionNotFound => "TransactionNotFound", - Error::TransactionConfirmed => "TransactionConfirmed", - Error::IrreplaceableTransaction => "IrreplaceableTransaction", - Error::FeeRateTooLow { .. } => "FeeRateTooLow", - Error::FeeTooLow { .. } => "FeeTooLow", - Error::MissingKeyOrigin(_) => "MissingKeyOrigin", - Error::Key(_) => "Key", - Error::ChecksumMismatch => "ChecksumMismatch", - Error::SpendingPolicyRequired(_) => "SpendingPolicyRequired", - Error::InvalidPolicyPathError(_) => "InvalidPolicyPathError", - Error::Signer(_) => "Signer", - Error::InvalidProgressValue(_) => "InvalidProgressValue", - Error::ProgressUpdateError => "ProgressUpdateError", - Error::InvalidOutpoint(_) => "InvalidOutpoint", - Error::Descriptor(_) => "Descriptor", - Error::AddressValidator(_) => "AddressValidator", - Error::Encode(_) => "Encode", - Error::Miniscript(_) => "Miniscript", - Error::Bip32(_) => "Bip32", - Error::Secp256k1(_) => "Secp256k1", - Error::Json(_) => "Json", - Error::Hex(_) => "Hex", - Error::Psbt(_) => "Psbt", - Error::Electrum(_) => "Electrum", - // Error::Esplora(_) => "Esplora", - // Error::CompactFilters(_) => "CompactFilters", - Error::Sled(_) => "Sled", - } - .to_string() +#[derive_ReprC] +#[repr(u16)] +#[derive(Debug)] +pub enum FfiError { + None, + InvalidU32Bytes, + Generic, + ScriptDoesntHaveAddressForm, + SingleRecipientMultipleOutputs, + SingleRecipientNoInputs, + NoRecipients, + NoUtxosSelected, + OutputBelowDustLimit, + InsufficientFunds, + BnBTotalTriesExceeded, + BnBNoExactMatch, + UnknownUtxo, + TransactionNotFound, + TransactionConfirmed, + IrreplaceableTransaction, + FeeRateTooLow, + FeeTooLow, + MissingKeyOrigin, + Key, + ChecksumMismatch, + SpendingPolicyRequired, + InvalidPolicyPathError, + Signer, + InvalidProgressValue, + ProgressUpdateError, + InvalidOutpoint, + Descriptor, + AddressValidator, + Encode, + Miniscript, + Bip32, + Secp256k1, + Json, + Hex, + Psbt, + Electrum, + // Esplora, + // CompactFilters, + Sled, +} + +impl From<&bdk::Error> for FfiError { + fn from(error: &bdk::Error) -> Self { + match error { + Error::InvalidU32Bytes(_) => FfiError::InvalidU32Bytes, + Error::Generic(_) => FfiError::Generic, + Error::ScriptDoesntHaveAddressForm => FfiError::ScriptDoesntHaveAddressForm, + Error::SingleRecipientMultipleOutputs => FfiError::SingleRecipientMultipleOutputs, + Error::SingleRecipientNoInputs => FfiError::SingleRecipientNoInputs, + Error::NoRecipients => FfiError::NoRecipients, + Error::NoUtxosSelected => FfiError::NoUtxosSelected, + Error::OutputBelowDustLimit(_) => FfiError::OutputBelowDustLimit, + Error::InsufficientFunds { .. } => FfiError::InsufficientFunds, + Error::BnBTotalTriesExceeded => FfiError::BnBTotalTriesExceeded, + Error::BnBNoExactMatch => FfiError::BnBNoExactMatch, + Error::UnknownUtxo => FfiError::UnknownUtxo, + Error::TransactionNotFound => FfiError::TransactionNotFound, + Error::TransactionConfirmed => FfiError::TransactionConfirmed, + Error::IrreplaceableTransaction => FfiError::IrreplaceableTransaction, + Error::FeeRateTooLow { .. } => FfiError::FeeRateTooLow, + Error::FeeTooLow { .. } => FfiError::FeeTooLow, + Error::MissingKeyOrigin(_) => FfiError::MissingKeyOrigin, + Error::Key(_) => FfiError::Key, + Error::ChecksumMismatch => FfiError::ChecksumMismatch, + Error::SpendingPolicyRequired(_) => FfiError::SpendingPolicyRequired, + Error::InvalidPolicyPathError(_) => FfiError::InvalidPolicyPathError, + Error::Signer(_) => FfiError::Signer, + Error::InvalidProgressValue(_) => FfiError::InvalidProgressValue, + Error::ProgressUpdateError => FfiError::ProgressUpdateError, + Error::InvalidOutpoint(_) => FfiError::InvalidOutpoint, + Error::Descriptor(_) => FfiError::Descriptor, + Error::AddressValidator(_) => FfiError::AddressValidator, + Error::Encode(_) => FfiError::Encode, + Error::Miniscript(_) => FfiError::Miniscript, + Error::Bip32(_) => FfiError::Bip32, + Error::Secp256k1(_) => FfiError::Secp256k1, + Error::Json(_) => FfiError::Json, + Error::Hex(_) => FfiError::Hex, + Error::Psbt(_) => FfiError::Psbt, + Error::Electrum(_) => FfiError::Electrum, + // Error::Esplora(_) => JniError::Esplora, + // Error::CompactFilters(_) => JniError::CompactFilters, + Error::Sled(_) => FfiError::Sled, + } + } } diff --git a/src/types.rs b/src/types.rs index c4dd5ac..5d856d6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,3 +1,4 @@ +use crate::error::FfiError; use ::safer_ffi::prelude::*; use safer_ffi::char_p::char_p_boxed; @@ -6,14 +7,14 @@ use safer_ffi::char_p::char_p_boxed; #[derive(Debug)] pub struct FfiResult { pub ok: T, - pub err: char_p_boxed, + pub err: FfiError, } #[derive_ReprC] #[repr(C)] #[derive(Debug)] pub struct FfiResultVoid { - pub err: char_p_boxed, + pub err: FfiError, } #[ffi_export] diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index bf12321..017a0ed 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -12,7 +12,7 @@ use safer_ffi::char_p::{char_p_boxed, char_p_ref}; use blockchain::BlockchainConfig; use database::DatabaseConfig; -use crate::error::get_name; +use crate::error::FfiError; use crate::types::{FfiResult, FfiResultVoid}; use std::ffi::CString; @@ -43,11 +43,11 @@ fn new_wallet_result( match wallet_result { Ok(w) => FfiResult { ok: Some(Box::new(OpaqueWallet { raw: w })), - err: char_p_boxed::from(CString::default()), + err: FfiError::None, }, Err(e) => FfiResult { ok: None, - err: char_p_boxed::try_from(get_name(&e)).unwrap(), + err: FfiError::from(&e), }, } } @@ -81,10 +81,10 @@ fn sync_wallet(opaque_wallet: &OpaqueWallet) -> FfiResultVoid { let int_result = opaque_wallet.raw.sync(log_progress(), Some(100)); match int_result { Ok(_v) => FfiResultVoid { - err: char_p_boxed::from(CString::default()), + err: FfiError::None, }, Err(e) => FfiResultVoid { - err: char_p_boxed::try_from(get_name(&e)).unwrap(), + err: FfiError::from(&e), }, } } @@ -96,11 +96,11 @@ fn new_address(opaque_wallet: &OpaqueWallet) -> FfiResult { match string_result { Ok(a) => FfiResult { ok: char_p_boxed::try_from(a).unwrap(), - err: char_p_boxed::from(CString::default()), + err: FfiError::None, }, Err(e) => FfiResult { ok: char_p_boxed::from(CString::default()), - err: char_p_boxed::try_from(get_name(&e)).unwrap(), + err: FfiError::from(&e), }, } } @@ -115,11 +115,11 @@ fn list_unspent(opaque_wallet: &OpaqueWallet) -> FfiResult = v.iter().map(|lu| LocalUtxo::from(lu)).collect(); repr_c::Vec::from(ve) }, - err: char_p_boxed::from(CString::default()), + err: FfiError::None, }, Err(e) => FfiResult { ok: repr_c::Vec::EMPTY, - err: char_p_boxed::try_from(get_name(&e)).unwrap(), + err: FfiError::from(&e), }, } }