Add get_merkle_proof()

This commit is contained in:
Sosthene 2025-06-30 16:00:31 +02:00
parent 4f278278b7
commit 1e1dbdf8df

View File

@ -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<JsValue> {
// 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))
}