From d5198695e8d038d2bf279506b88fe2e56df0fb97 Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 19 Jun 2024 07:17:02 -0600 Subject: [PATCH 1/3] feat: poseidon hash for c bindings --- Cargo.lock | 2 +- dojo.h | 2 ++ dojo.hpp | 2 ++ src/c/mod.rs | 25 ++++++++++++++++++++++++- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94b25c8..7dedf37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2537,7 +2537,7 @@ dependencies = [ [[package]] name = "dojo-c" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome)", diff --git a/dojo.h b/dojo.h index 71103be..6a64021 100644 --- a/dojo.h +++ b/dojo.h @@ -650,6 +650,8 @@ struct ResultCArrayFieldElement bytearray_serialize(const char *str); struct Resultc_char bytearray_deserialize(const struct FieldElement *felts, uintptr_t felts_len); +struct ResultFieldElement poseidon_hash(const char *const *felts, uintptr_t felts_len); + struct ResultFieldElement typed_data_encode(const char *typed_data, struct FieldElement address); struct FieldElement signing_key_new(void); diff --git a/dojo.hpp b/dojo.hpp index fce8457..a7d5cf8 100644 --- a/dojo.hpp +++ b/dojo.hpp @@ -835,6 +835,8 @@ Result> bytearray_serialize(const char *str); Result bytearray_deserialize(const FieldElement *felts, uintptr_t felts_len); +Result poseidon_hash(const char *const *felts, uintptr_t felts_len); + Result typed_data_encode(const char *typed_data, FieldElement address); FieldElement signing_key_new(); diff --git a/src/c/mod.rs b/src/c/mod.rs index 3a1f6c4..ecd61bb 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -16,7 +16,7 @@ use starknet::core::utils::{ use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::{JsonRpcClient, Provider as _}; use starknet::signers::{LocalWallet, SigningKey, VerifyingKey}; -use starknet_crypto::FieldElement; +use starknet_crypto::{poseidon_hash_many, FieldElement}; use std::ffi::{c_void, CStr, CString}; use std::ops::Deref; use std::os::raw::c_char; @@ -373,6 +373,29 @@ pub unsafe extern "C" fn bytearray_deserialize( Result::Ok(CString::new(bytearray).unwrap().into_raw()) } +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn poseidon_hash( + felts: *const *const c_char, + felts_len: usize, +) -> Result { + let felts: &[*const c_char] = unsafe { std::slice::from_raw_parts(felts, felts_len) }; + + let felts = match felts + .iter() + .map(|f| { + let k = unsafe { CStr::from_ptr(*f) }.to_string_lossy().to_string(); + FieldElement::from_hex_be(&k) + }) + .collect::, _>>() + { + Ok(felts) => felts.to_vec(), + Err(e) => return Result::Err(e.into()), + }; + + Result::Ok((&poseidon_hash_many(&felts)).into()) +} + #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn typed_data_encode( From 7d7f75231542f18cc7650baf9f0c1c9a34030e02 Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 19 Jun 2024 07:24:55 -0600 Subject: [PATCH 2/3] feat: add poseidon hash to wasm --- src/wasm/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs index 4acb104..0c213ae 100644 --- a/src/wasm/mod.rs +++ b/src/wasm/mod.rs @@ -18,7 +18,7 @@ use starknet::core::utils::{ use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::{JsonRpcClient, Provider as _}; use starknet::signers::{LocalWallet, SigningKey, VerifyingKey}; -use starknet_crypto::Signature; +use starknet_crypto::{Signature, poseidon_hash_many}; use stream_cancel::{StreamExt as _, Tripwire}; use torii_relay::typed_data::TypedData; use torii_relay::types::Message; @@ -693,6 +693,17 @@ pub fn bytearray_deserialize(felts: Vec) -> Result { } } +#[wasm_bindgen(js_name = poseidonHash)] +pub fn poseidon_hash(inputs: Vec) -> Result { + let inputs = inputs + .into_iter() + .map(|i| FieldElement::from_str(i.as_str())) + .collect::, _>>() + .map_err(|e| JsValue::from(format!("failed to parse inputs: {e}")))?; + + Ok(format!("{:#x}", poseidon_hash_many(&inputs))) +} + #[wasm_bindgen] impl Client { #[wasm_bindgen(js_name = getEntities)] From eee5bd246dc9b6b2567599005966e410cdc266ba Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 19 Jun 2024 07:27:39 -0600 Subject: [PATCH 3/3] refactor: use types::FieldElement --- dojo.h | 2 +- dojo.hpp | 2 +- src/c/mod.rs | 18 +++++------------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/dojo.h b/dojo.h index 6a64021..ee38fde 100644 --- a/dojo.h +++ b/dojo.h @@ -650,7 +650,7 @@ struct ResultCArrayFieldElement bytearray_serialize(const char *str); struct Resultc_char bytearray_deserialize(const struct FieldElement *felts, uintptr_t felts_len); -struct ResultFieldElement poseidon_hash(const char *const *felts, uintptr_t felts_len); +struct ResultFieldElement poseidon_hash(const struct FieldElement *felts, uintptr_t felts_len); struct ResultFieldElement typed_data_encode(const char *typed_data, struct FieldElement address); diff --git a/dojo.hpp b/dojo.hpp index a7d5cf8..0312a7a 100644 --- a/dojo.hpp +++ b/dojo.hpp @@ -835,7 +835,7 @@ Result> bytearray_serialize(const char *str); Result bytearray_deserialize(const FieldElement *felts, uintptr_t felts_len); -Result poseidon_hash(const char *const *felts, uintptr_t felts_len); +Result poseidon_hash(const FieldElement *felts, uintptr_t felts_len); Result typed_data_encode(const char *typed_data, FieldElement address); diff --git a/src/c/mod.rs b/src/c/mod.rs index ecd61bb..77513e8 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -376,22 +376,14 @@ pub unsafe extern "C" fn bytearray_deserialize( #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn poseidon_hash( - felts: *const *const c_char, + felts: *const types::FieldElement, felts_len: usize, ) -> Result { - let felts: &[*const c_char] = unsafe { std::slice::from_raw_parts(felts, felts_len) }; - - let felts = match felts + let felts = unsafe { std::slice::from_raw_parts(felts, felts_len) }; + let felts = felts .iter() - .map(|f| { - let k = unsafe { CStr::from_ptr(*f) }.to_string_lossy().to_string(); - FieldElement::from_hex_be(&k) - }) - .collect::, _>>() - { - Ok(felts) => felts.to_vec(), - Err(e) => return Result::Err(e.into()), - }; + .map(|f| (&f.clone()).into()) + .collect::>(); Result::Ok((&poseidon_hash_many(&felts)).into()) }