diff --git a/src/pcd.rs b/src/pcd.rs index d051607..3cc9e76 100644 --- a/src/pcd.rs +++ b/src/pcd.rs @@ -10,13 +10,15 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use sp_client::{ bitcoin::{ - consensus::serialize, hashes::{sha256t_hash_newtype, Hash, HashEngine}, secp256k1::PublicKey, OutPoint + hashes::Hash, secp256k1::PublicKey, OutPoint }, silentpayments::SilentPaymentAddress, }; use tsify::Tsify; -use crate::serialization::OutPointMemberMap; +use crate::hash::AnkPcdHash; +use crate::serialization::{ciborium_serialize, OutPointMemberMap}; +use crate::ROLESLABEL; use crate::{ signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof}, serialization::hex_array_btree @@ -105,29 +107,6 @@ impl Member { } } -sha256t_hash_newtype! { - pub struct AnkPcdTag = hash_str("4nk/Pcd"); - - #[hash_newtype(forward)] - pub struct AnkPcdHash(_); -} - -impl AnkPcdHash { - pub fn from_value(value: &Value) -> Self { - let mut eng = AnkPcdHash::engine(); - eng.input(value.to_string().as_bytes()); - AnkPcdHash::from_engine(eng) - } - - /// Adding the root_commitment guarantee that the same clear value across different processes wont' produce the same hash - pub fn from_value_with_outpoint(value: &[u8], outpoint: &[u8]) -> Self { - let mut eng = AnkPcdHash::engine(); - eng.input(outpoint); - eng.input(value); - AnkPcdHash::from_engine(eng) - } -} - #[derive(Serialize, Deserialize)] pub struct FileBlob { r#type: String, @@ -166,9 +145,8 @@ impl TryFrom> for Pcd { fn try_from(file_blob_map: BTreeMap) -> Result { let map: Result>> = file_blob_map.iter().map(|(key, value)| { - let mut writer = vec![]; - ciborium::into_writer(value, &mut writer)?; - Ok((key.clone(), writer)) + let serialized = crate::serialization::ciborium_serialize(value)?; + Ok((key.clone(), serialized)) }).collect(); Ok(Pcd(map?)) @@ -208,21 +186,17 @@ pub struct PcdCommitments(#[serde(with = "hex_array_btree")] #[tsify(type = "Rec impl PcdCommitments { /// Creates a new commitments map with both permissioned and public data, + roles pub fn new(commited_in: &OutPoint, attributes: &Pcd, roles: &Roles) -> Result { - let serialized_outpoint = serialize(commited_in); let mut field2hash: BTreeMap = BTreeMap::new(); for (field, value) in attributes.iter() { - let mut value_bin = serde_json::to_string(&value)?.into_bytes(); - value_bin.extend_from_slice(field.as_bytes()); - let tagged_hash = AnkPcdHash::from_value_with_outpoint(&value_bin, &serialized_outpoint); + let tagged_hash = AnkPcdHash::from_pcd_value(value.as_slice(), field.as_bytes(), commited_in); field2hash.insert(field.to_owned(), tagged_hash.to_byte_array()); } if roles.len() > 0 { - let serialized_roles = roles.to_bytes()?; + let roles_label = String::from(ROLESLABEL); + let roles_hash = AnkPcdHash::from_pcd_value(roles.to_bytes()?.as_slice(), roles_label.as_bytes(), commited_in); - let roles_hash = AnkPcdHash::from_value_with_outpoint(&serialized_roles, &serialized_outpoint); - - field2hash.insert("roles".to_owned(), roles_hash.to_byte_array()); + field2hash.insert(roles_label, roles_hash.to_byte_array()); } // We should probably return an error if roles are empty Ok(Self(field2hash)) @@ -237,12 +211,9 @@ impl PcdCommitments { } pub fn update_with_value(&mut self, outpoint: &OutPoint, field: &str, new_value: &[u8]) -> Result<()> { - let serialized_outpoint = serialize(outpoint); if let Some(old_hash) = self.get_mut(field) { // We hash the new_value - let mut value_bin = new_value.to_vec(); - value_bin.extend_from_slice(field.as_bytes()); - let tagged_hash = AnkPcdHash::from_value_with_outpoint(&value_bin, &serialized_outpoint); + let tagged_hash = AnkPcdHash::from_pcd_value(new_value, field.as_bytes(), outpoint); *old_hash = tagged_hash.to_byte_array(); Ok(()) } else { @@ -485,9 +456,9 @@ impl Roles { pub fn is_empty(&self) -> bool { self.0.is_empty() } - + pub fn to_bytes(&self) -> Result> { - serde_json::to_vec(&self.0).map_err(|e| Error::msg(e.to_string())) + ciborium_serialize(&self.0) } pub fn len(&self) -> usize {