Repository: ergoplatform/sigma-rust (language: rust)

Issue:
Secret key input in JS API
String might be the best choice. Check out byte array.


Discussion / hints:

Fix patch:
diff --git a/bindings/ergo-wallet-lib-wasm/src/secret_key.rs b/bindings/ergo-wallet-lib-wasm/src/secret_key.rs
index 97cda4637..9ab6f9c35 100644
--- a/bindings/ergo-wallet-lib-wasm/src/secret_key.rs
+++ b/bindings/ergo-wallet-lib-wasm/src/secret_key.rs
@@ -1,4 +1,7 @@
 //! Secret key
+use std::convert::TryInto;
+
+use sigma_tree::sigma_protocol::DlogProverInput;
 use sigma_tree::wallet;
 use wasm_bindgen::prelude::*;
 
@@ -16,6 +19,20 @@ impl SecretKey {
         SecretKey(wallet::secret_key::SecretKey::random_dlog())
     }
 
+    /// Parse dlog secret key from bytes (SEC-1-encoded scalar)
+    pub fn dlog_from_bytes(bytes: &[u8]) -> Result<SecretKey, JsValue> {
+        let sized_bytes: &[u8; DlogProverInput::SIZE_BYTES] = bytes.try_into().map_err(|_| {
+            JsValue::from_str(&format!(
+                "expected byte array of size {}, found {}",
+                DlogProverInput::SIZE_BYTES,
+                bytes.len()
+            ))
+        })?;
+        wallet::secret_key::SecretKey::dlog_from_bytes(sized_bytes)
+            .map(SecretKey)
+            .ok_or_else(|| JsValue::from_str("failed to parse scalar"))
+    }
+
     /// Address (encoded public image)
     pub fn get_address(&self) -> Address {
         self.0.get_address_from_public_image().into()
diff --git a/sigma-tree/src/lib.rs b/sigma-tree/src/lib.rs
index 29fd6abdb..35668e284 100644
--- a/sigma-tree/src/lib.rs
+++ b/sigma-tree/src/lib.rs
@@ -22,8 +22,8 @@ pub mod ast;
 pub mod chain;
 pub mod eval;
 pub mod sigma_protocol;
+pub mod util;
 pub mod wallet;
-
 pub use ergo_tree::*;
 
 #[cfg(test)]
diff --git a/sigma-tree/src/sigma_protocol/private_input.rs b/sigma-tree/src/sigma_protocol/private_input.rs
index c300fb85c..b9a224f5d 100644
--- a/sigma-tree/src/sigma_protocol/private_input.rs
+++ b/sigma-tree/src/sigma_protocol/private_input.rs
@@ -1,4 +1,7 @@
+use crate::util::IntoOption;
+
 use super::{dlog_group, ProveDlog};
+use elliptic_curve::FromBytes;
 use k256::Scalar;
 
 /// Secret key of discrete logarithm signature protocol
@@ -9,6 +12,9 @@ pub struct DlogProverInput {
 }
 
 impl DlogProverInput {
+    /// Scalar(secret key) size in bytes
+    pub const SIZE_BYTES: usize = 32;
+
     /// generates random secret in the range [0, n), where n is DLog group order.
     pub fn random() -> DlogProverInput {
         DlogProverInput {
@@ -16,6 +22,15 @@ impl DlogProverInput {
         }
     }
 
+    /// Attempts to parse the given byte array as an SEC-1-encoded scalar(secret key).
+    /// Returns None if the byte array does not contain a big-endian integer in the range
+    /// [0, modulus).
+    pub fn from_bytes(bytes: &[u8; DlogProverInput::SIZE_BYTES]) -> Option<DlogProverInput> {
+        Scalar::from_bytes(bytes.into())
+            .into_option()
+            .map(DlogProverInput::from)
+    }
+
     /// public key of discrete logarithm signature protocol
     pub fn public_image(&self) -> ProveDlog {
         // test it, see https://github.com/ergoplatform/sigma-rust/issues/38
@@ -24,6 +39,12 @@ impl DlogProverInput {
     }
 }
 
+impl From<Scalar> for DlogProverInput {
+    fn from(w: Scalar) -> Self {
+        DlogProverInput { w }
+    }
+}
+
 /// Private inputs (secrets)
 pub enum PrivateInput {
     /// Discrete logarithm prover input
diff --git a/sigma-tree/src/util.rs b/sigma-tree/src/util.rs
new file mode 100644
index 000000000..1df837099
--- /dev/null
+++ b/sigma-tree/src/util.rs
@@ -0,0 +1,19 @@
+//! Utilities
+
+use elliptic_curve::subtle::CtOption;
+
+/// Convert to Option<T>
+pub trait IntoOption<T> {
+    /// Get Option<T>
+    fn into_option(self) -> Option<T>;
+}
+
+impl<T> IntoOption<T> for CtOption<T> {
+    fn into_option(self) -> Option<T> {
+        if self.is_some().into() {
+            Some(self.unwrap())
+        } else {
+            None
+        }
+    }
+}
diff --git a/sigma-tree/src/wallet/secret_key.rs b/sigma-tree/src/wallet/secret_key.rs
index 77af243dd..d4659aa53 100644
--- a/sigma-tree/src/wallet/secret_key.rs
+++ b/sigma-tree/src/wallet/secret_key.rs
@@ -15,6 +15,11 @@ impl SecretKey {
         SecretKey::DlogSecretKey(DlogProverInput::random())
     }
 
+    /// Parse DlogSecretKey from bytes (SEC-1-encoded scalar)
+    pub fn dlog_from_bytes(bytes: &[u8; DlogProverInput::SIZE_BYTES]) -> Option<SecretKey> {
+        DlogProverInput::from_bytes(bytes).map(SecretKey::DlogSecretKey)
+    }
+
     /// Address (encoded public image)
     pub fn get_address_from_public_image(&self) -> Address {
         match self {


Test patch: