Sfoglia il codice sorgente

sdk: Merkle root queries

Luther Blissett 3 anni fa
parent
commit
851ecd2667
3 ha cambiato i file con 86 aggiunte e 1 eliminazioni
  1. 59 0
      src/sdk/src/crypto/merkle_node.rs
  2. 4 0
      src/sdk/src/crypto/mod.rs
  3. 23 1
      src/sdk/src/state.rs

+ 59 - 0
src/sdk/src/crypto/merkle_node.rs

@@ -0,0 +1,59 @@
+use core::str::FromStr;
+use std::io;
+
+use pasta_curves::{group::ff::PrimeField, pallas};
+
+/// The `MerkleNode` is represented as a base field element.
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct MerkleNode(pallas::Base);
+
+impl MerkleNode {
+    /// Reference the raw inner base field element
+    pub fn inner(&self) -> pallas::Base {
+        self.0
+    }
+
+    /// Try to create a `MerkleNode` type from the given 32 bytes.
+    /// Returns `Some` if the bytes fit in the base field, and `None` if not.
+    pub fn from_bytes(bytes: [u8; 32]) -> Option<Self> {
+        let n = pallas::Base::from_repr(bytes);
+        match bool::from(n.is_some()) {
+            true => Some(Self(n.unwrap())),
+            false => None,
+        }
+    }
+
+    /// Convert the `MerkleNode` type into 32 raw bytes
+    pub fn to_bytes(&self) -> [u8; 32] {
+        self.0.to_repr()
+    }
+}
+
+impl From<pallas::Base> for MerkleNode {
+    fn from(x: pallas::Base) -> Self {
+        Self(x)
+    }
+}
+
+impl FromStr for MerkleNode {
+    type Err = io::Error;
+
+    /// Tries to decode a base58 string into a `MerkleNode` type.
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let bytes = match bs58::decode(s).into_vec() {
+            Ok(v) => v,
+            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
+        };
+
+        if bytes.len() != 32 {
+            return Err(io::Error::new(io::ErrorKind::Other, "Length of decoded bytes is not 32"))
+        }
+
+        if let Some(merkle_node) = Self::from_bytes(bytes.try_into().unwrap()) {
+            return Ok(merkle_node)
+        }
+
+        return Err(io::Error::new(io::ErrorKind::Other, "Invalid bytes for MerkleNode"))
+    }
+}

+ 4 - 0
src/sdk/src/crypto/mod.rs

@@ -9,6 +9,10 @@
 //! If you feel like trying, please help out with this migration, but do
 //! it properly, with care, and write documentation while you're at it.
 
+/// Merkle node definitions
+pub mod merkle_node;
+pub use merkle_node::MerkleNode;
+
 /// Nullifier definitions
 pub mod nullifier;
 pub use nullifier::Nullifier;

+ 23 - 1
src/sdk/src/state.rs

@@ -1,4 +1,7 @@
-use super::{crypto::Nullifier, error::ContractError};
+use super::{
+    crypto::{MerkleNode, Nullifier},
+    error::ContractError,
+};
 
 pub fn nullifier_exists(nullifier: &Nullifier) -> Result<bool, ContractError> {
     #[cfg(target_arch = "wasm32")]
@@ -18,7 +21,26 @@ pub fn nullifier_exists(nullifier: &Nullifier) -> Result<bool, ContractError> {
     todo!("nullifier_exists({:?}", nullifier);
 }
 
+pub fn is_valid_merkle(merkle_root: &MerkleNode) -> Result<bool, ContractError> {
+    #[cfg(target_arch = "wasm32")]
+    unsafe {
+        // Convert to bytes, and pass pointer to first byte in slice to the function.
+        let mr = merkle_root.to_bytes();
+        return match is_valid_merkle_(&mr as *const u8, 32) {
+            0 => Ok(false),
+            1 => Ok(true),
+            -1 => Err(ContractError::ValidMerkleCheck),
+            -2 => Err(ContractError::Internal),
+            _ => unreachable!(),
+        }
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    todo!("is_valid_merkle({:?}", merkle_root);
+}
+
 #[cfg(target_arch = "wasm32")]
 extern "C" {
     fn nullifier_exists_(ptr: *const u8, len: u32) -> i32;
+    fn is_valid_merkle_(ptr: *const u8, len: u32) -> i32;
 }