From 6ea6232e9c1c301a6abd19dcdba983b930694a54 Mon Sep 17 00:00:00 2001 From: Sosthene Date: Mon, 30 Jun 2025 16:00:31 +0200 Subject: [PATCH] Add get_merkle_proof() --- src/api.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/api.rs b/src/api.rs index 6e01816..485edd9 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1739,3 +1739,56 @@ pub fn hash_value(value: JsValue, commited_in: String, label: String) -> ApiResu let hash = AnkPcdHash::from_pcd_value(encoded_value.as_slice(), label.as_bytes(), &outpoint); Ok(hash.as_byte_array().to_lower_hex_string()) } +#[wasm_bindgen] +/// Generate a merkle proof for a specific attribute in a process state. +/// +/// This function creates a merkle proof that proves the existence of a specific attribute +/// in a given state of a process. The proof can be used to verify that the attribute +/// was indeed part of the state without revealing the entire state. +/// +/// # Arguments +/// * `process_state` - The process state object as a JavaScript value +/// * `attribute_name` - The name of the attribute to generate a proof for +/// +/// # Returns +/// A JavaScript object containing: +/// * `proof` - The merkle proof as a hex string +/// * `root` - The merkle root (state_id) as a hex string +/// * `attribute` - The attribute name that was proven +/// * `attribute_index` - The index of the attribute in the merkle tree +/// +/// # Errors +/// * "Failed to deserialize process state" - If the process state cannot be deserialized from JsValue +/// * "Attribute not found in state" - If the attribute doesn't exist in the state +pub fn get_merkle_proof(process_state: JsValue, attribute_name: String) -> ApiResult { + // Deserialize the process state from JsValue + let state: ProcessState = serde_wasm_bindgen::from_value(process_state) + .map_err(|_| ApiError::new("Failed to deserialize process state".to_owned()))?; + + // Create merkle tree from the PCD commitments + let merkle_tree = state.pcd_commitment.create_merkle_tree()?; + + // Find the index of the attribute in the commitments + let attribute_index = state.pcd_commitment.find_index_of(&attribute_name) + .ok_or(ApiError::new("Attribute not found in state".to_owned()))?; + + // Generate the merkle proof for the attribute + let proof = merkle_tree.proof(&[attribute_index]); + + // Convert the proof to a format that can be serialized to JavaScript + let proof_bytes = proof.to_bytes(); + let proof_hex = proof_bytes.to_lower_hex_string(); + + // Create a result object with the proof and additional metadata + let result = Object::new(); + Reflect::set(&result, &JsValue::from_str("proof"), &JsValue::from_str(&proof_hex)) + .map_err(|_| ApiError::new("Failed to set proof field".to_owned()))?; + Reflect::set(&result, &JsValue::from_str("root"), &JsValue::from_str(&state.state_id.to_lower_hex_string())) + .map_err(|_| ApiError::new("Failed to set root field".to_owned()))?; + Reflect::set(&result, &JsValue::from_str("attribute"), &JsValue::from_str(&attribute_name)) + .map_err(|_| ApiError::new("Failed to set attribute field".to_owned()))?; + Reflect::set(&result, &JsValue::from_str("attribute_index"), &JsValue::from_f64(attribute_index as f64)) + .map_err(|_| ApiError::new("Failed to set attribute_index field".to_owned()))?; + + Ok(JsValue::from(result)) +}