Move hashing into hash mod and refactor hash code

This commit is contained in:
NicolasCantu 2025-06-06 22:45:17 +02:00
parent a3cf2517b3
commit 58730c48f4

View File

@ -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<BTreeMap<String, FileBlob>> for Pcd {
fn try_from(file_blob_map: BTreeMap<String, FileBlob>) -> Result<Self> {
let map: Result<BTreeMap<String, Vec<u8>>> = 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<Self> {
let serialized_outpoint = serialize(commited_in);
let mut field2hash: BTreeMap<String, [u8; 32]> = 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<Vec<u8>> {
serde_json::to_vec(&self.0).map_err(|e| Error::msg(e.to_string()))
ciborium_serialize(&self.0)
}
pub fn len(&self) -> usize {