From 7d9c95bb66d613b46ed1454049216b1acc72f2af Mon Sep 17 00:00:00 2001
From: librelois <c@elo.tf>
Date: Mon, 8 Feb 2021 18:26:30 +0100
Subject: [PATCH] feat(dubp): add method getDewifSecretCodeLen

---
 Cargo.lock                        | 18 ++++++++++++++----
 Cargo.toml                        |  5 ++++-
 native/dubp_rs/Cargo.toml         |  2 +-
 native/dubp_rs/src/dewif.rs       | 15 +++++++++++++++
 native/dubp_rs/src/inputs.rs      |  1 +
 native/dubp_rs/src/lib.rs         | 23 +++++++++++++++++++++++
 native/dubp_rs/src/secret_code.rs | 26 +++++++++++++++++++-------
 packages/dubp_rs/lib/dubp.dart    | 29 ++++++++++++++++++++++++++++-
 8 files changed, 105 insertions(+), 14 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 70861c7e..a28e4d54 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -222,9 +222,9 @@ dependencies = [
 
 [[package]]
 name = "cryptoxide"
-version = "0.2.1"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da24927b5b899890bcb29205436c957b7892ec3a3fbffce81d710b9611e77778"
+checksum = "f2824e117f942b77e942b14162316711d66f07d14b0f37a44fa4b4cad592b8fa"
 
 [[package]]
 name = "dart-bindgen"
@@ -261,9 +261,9 @@ dependencies = [
 
 [[package]]
 name = "dup-crypto"
-version = "0.38.0"
+version = "0.40.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b1f8913ba1b77dbbf419c2aeabc566ccca5e77385b6738bb408cd9a9e7bbb86"
+checksum = "ba9cba3d83bf946b9e2d3b444f98df563d6ffefa94579bdfc6f06b158cd872a9"
 dependencies = [
  "aes",
  "arrayvec",
@@ -272,6 +272,7 @@ dependencies = [
  "bs58",
  "byteorder",
  "cryptoxide",
+ "ed25519-bip32",
  "getrandom",
  "once_cell",
  "ring",
@@ -281,6 +282,15 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "ed25519-bip32"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8827180a2b511141fbe49141e50b31a8d542465e0fb572f81f36feea2addfe92"
+dependencies = [
+ "cryptoxide",
+]
+
 [[package]]
 name = "fast-threadpool"
 version = "0.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index 81a6dfc0..90c31711 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,4 +4,7 @@ members = ["native/dubp_rs"]
 [profile.release]
 lto = true
 codegen-units = 1
-debug = true
\ No newline at end of file
+debug = true
+
+[patch.crates-io]
+#dup-crypto = { path = "/home/elois/dev/duniter/libs/dubp-rs-libs/crypto" }
diff --git a/native/dubp_rs/Cargo.toml b/native/dubp_rs/Cargo.toml
index 1b138b39..5d104fa9 100644
--- a/native/dubp_rs/Cargo.toml
+++ b/native/dubp_rs/Cargo.toml
@@ -10,7 +10,7 @@ crate-type = ["rlib"]
 
 [dependencies]
 allo-isolate = "0.1.6"
-dup-crypto = { version = "0.38.0", features = ["dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] }
+dup-crypto = { version = "0.40.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] }
 fast-threadpool = { version = "0.3.0", default-features = false }
 once_cell = { version = "1.3.1", default-features = false, features = ["std"] }
 thiserror = "1.0.23"
diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs
index 80fa7ba2..70e25623 100644
--- a/native/dubp_rs/src/dewif.rs
+++ b/native/dubp_rs/src/dewif.rs
@@ -64,6 +64,21 @@ pub(super) fn gen_dewif(
     Ok(vec![dewif, secret_code, pubkey])
 }
 
+pub(super) fn get_secret_code_len(
+    currency: Currency,
+    dewif: &str,
+    member_wallet: bool,
+    secret_code_type: SecretCodeType,
+) -> Result<String, DubpError> {
+    let log_n = dup_crypto::dewif::read_dewif_log_n(ExpectedCurrency::Specific(currency), dewif)
+        .map_err(DubpError::DewifReadError)?;
+
+    Ok(
+        crate::secret_code::compute_secret_code_len(member_wallet, secret_code_type, log_n)?
+            .to_string(),
+    )
+}
+
 pub(super) fn get_pubkey(currency: Currency, dewif: &str, pin: &str) -> Result<String, DubpError> {
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
diff --git a/native/dubp_rs/src/inputs.rs b/native/dubp_rs/src/inputs.rs
index 79595802..557e0c4c 100644
--- a/native/dubp_rs/src/inputs.rs
+++ b/native/dubp_rs/src/inputs.rs
@@ -15,6 +15,7 @@
 
 use crate::*;
 
+#[derive(Clone, Copy, Debug)]
 pub(crate) enum SecretCodeType {
     Digits,
     Letters,
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 91a28114..172cab2f 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -167,6 +167,29 @@ pub extern "C" fn gen_mnemonic(port: i64, language: u32) {
     exec_async(port, || u32_to_language(language), mnemonic::gen_mnemonic)
 }
 
+#[no_mangle]
+pub extern "C" fn get_dewif_secret_code_len(
+    port: i64,
+    currency: *const raw::c_char,
+    dewif: *const raw::c_char,
+    member_wallet: u32,
+    secret_code_type: u32,
+) {
+    exec_async(
+        port,
+        || {
+            let currency = parse_currency(char_ptr_to_str(currency)?)?;
+            let dewif = char_ptr_to_str(dewif)?;
+            let member_wallet = member_wallet != 0;
+            let secret_code_type = SecretCodeType::from(secret_code_type);
+            Ok((currency, dewif, member_wallet, secret_code_type))
+        },
+        |(currency, dewif, member_wallet, secret_code_type)| {
+            dewif::get_secret_code_len(currency, dewif, member_wallet, secret_code_type)
+        },
+    )
+}
+
 #[no_mangle]
 pub extern "C" fn get_dewif_pubkey(
     port: i64,
diff --git a/native/dubp_rs/src/secret_code.rs b/native/dubp_rs/src/secret_code.rs
index 4b29dca7..3666705c 100644
--- a/native/dubp_rs/src/secret_code.rs
+++ b/native/dubp_rs/src/secret_code.rs
@@ -15,33 +15,45 @@
 
 use crate::*;
 
-pub(crate) fn gen_secret_code(
+pub(crate) fn compute_secret_code_len(
     member_wallet: bool,
     secret_code_type: SecretCodeType,
     log_n: u8,
-) -> Result<String, DubpError> {
+) -> Result<usize, DubpError> {
     match secret_code_type {
         SecretCodeType::Digits => {
             if member_wallet {
                 Err(DubpError::DigitsCodeForbidForMemberWallet)
             } else if log_n >= 15 {
-                gen_random_digits(7)
+                Ok(7)
             } else {
-                gen_random_digits(8)
+                Ok(8)
             }
         }
         SecretCodeType::Letters => {
             if member_wallet {
-                gen_random_letters(10)
+                Ok(10)
             } else if log_n >= 15 {
-                gen_random_letters(5)
+                Ok(5)
             } else {
-                gen_random_letters(6)
+                Ok(6)
             }
         }
     }
 }
 
+pub(crate) fn gen_secret_code(
+    member_wallet: bool,
+    secret_code_type: SecretCodeType,
+    log_n: u8,
+) -> Result<String, DubpError> {
+    let secret_code_len = compute_secret_code_len(member_wallet, secret_code_type, log_n)?;
+    match secret_code_type {
+        SecretCodeType::Digits => gen_random_digits(secret_code_len),
+        SecretCodeType::Letters => gen_random_letters(secret_code_len),
+    }
+}
+
 fn gen_random_digits(n: usize) -> Result<String, DubpError> {
     let mut digits_string = dup_crypto::rand::gen_u32()
         .map_err(|_| DubpError::RandErr)?
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index 7aa5c26c..4d246e6c 100644
--- a/packages/dubp_rs/lib/dubp.dart
+++ b/packages/dubp_rs/lib/dubp.dart
@@ -116,7 +116,6 @@ class DubpRust {
     return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2]));
   }
 
-
   /// Generate a wallet from a mnemonic phrase.
   ///
   /// If the mnemonic is not in English, you must indicate the language of
@@ -165,6 +164,24 @@ class DubpRust {
     return completer.future;
   }
 
+  /// Get secret code length of `dewif` keypair.
+  static Future<int> getDewifSecretCodeLen(
+      {String currency = "g1",
+      String dewif,
+      SecretCodeType secretCodeType = SecretCodeType.letters}) async {
+    final completer = Completer<int>();
+    final sendPort =
+        singleCompletePort<int, String>(completer, callback: _handleErrInt);
+    native.get_dewif_secret_code_len(
+      sendPort.nativePort,
+      Utf8.toUtf8(currency),
+      Utf8.toUtf8(dewif),
+      0,
+      secretCodeType.index,
+    );
+    return completer.future;
+  }
+
   /// Get public key (in base 58) of legacy wallet (password + salt)
   ///
   /// This deprecated method must be used only for compatibility purpose !
@@ -271,4 +288,14 @@ class DubpRust {
       return arr;
     }
   }
+
+  static int _handleErrInt(String res) {
+    if (res.startsWith('DUBP_RS_ERROR: ')) {
+      final error = res;
+      print(error);
+      throw error;
+    } else {
+      return int.parse(res);
+    }
+  }
 }
-- 
GitLab