Add serde support.

This adds the `serialization-serde` feature, which implements
serde's `Serialize` and `Deserialize` traits for `Proof` and `Lemma`.

Fixes #30
This commit is contained in:
Andreas Fackler
2018-05-15 17:20:09 +02:00
committed by Romain Ruetschi
parent b20059f773
commit cc7fccc97c
5 changed files with 54 additions and 0 deletions

View File

@ -3,6 +3,8 @@
## [Unreleased](https://github.com/SpinResearch/merkle.rs/compare/1.6.0...master)
- Support serde with the feature flag `serialization-serde`.
> Nothing yet.
## [1.6.0](https://github.com/SpinResearch/merkle.rs/compare/1.5.0...1.6.0) - 2018-05-15

View File

@ -20,9 +20,15 @@ categories = ["data-structures", "cryptography"]
[dependencies]
ring = "^0.12.0"
protobuf = { version = "^1.6.0", optional = true }
serde = { version = "^1.0.55", optional = true }
serde_derive = { version = "^1.0.55", optional = true }
[dev-dependencies]
serde_json = "1.0.17"
[features]
serialization-protobuf = [ "protobuf" ]
serialization-serde = [ "serde", "serde_derive" ]
[package.metadata.release]
sign-commit = true

View File

@ -13,6 +13,12 @@ extern crate ring;
#[cfg(feature = "serialization-protobuf")]
extern crate protobuf;
#[cfg(feature = "serialization-serde")]
extern crate serde;
#[cfg(feature = "serialization-serde")]
#[macro_use]
extern crate serde_derive;
mod merkletree;
pub use merkletree::MerkleTree;

View File

@ -9,9 +9,11 @@ use hashutils::HashUtils;
/// An inclusion proof represent the fact that a `value` is a member
/// of a `MerkleTree` with root hash `root_hash`, and hash function `algorithm`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Proof<T> {
/// The hashing algorithm used in the original `MerkleTree`
#[cfg_attr(feature = "serialization-serde", serde(with = "algorithm_serde"))]
pub algorithm: &'static Algorithm,
/// The hash of the root of the original `MerkleTree`
@ -24,6 +26,30 @@ pub struct Proof<T> {
pub value: T,
}
#[cfg(feature = "serialization-serde")]
mod algorithm_serde {
use ring::digest::{self, Algorithm};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error;
pub fn serialize<S: Serializer>(algorithm: &&'static Algorithm, se: S)
-> Result<S::Ok, S::Error> {
// The `Debug` implementation of `Algorithm` prints its ID.
format!("{:?}", algorithm).serialize(se)
}
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<&'static Algorithm, D::Error> {
match Deserialize::deserialize(de)? {
"SHA1" => Ok(&digest::SHA1),
"SHA256" => Ok(&digest::SHA256),
"SHA384" => Ok(&digest::SHA384),
"SHA512" => Ok(&digest::SHA512),
"SHA512_256" => Ok(&digest::SHA512_256),
_ => Err(D::Error::custom("unknown hash algorithm")),
}
}
}
impl<T: PartialEq> PartialEq for Proof<T> {
fn eq(&self, other: &Proof<T>) -> bool {
self.root_hash == other.root_hash && self.lemma == other.lemma && self.value == other.value
@ -107,6 +133,7 @@ impl<T> Proof<T> {
/// A `Lemma` holds the hash of a node, the hash of its sibling node,
/// and a sub lemma, whose `node_hash`, when combined with this `sibling_hash`
/// must be equal to this `node_hash`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lemma {
pub node_hash: Vec<u8>,
@ -173,6 +200,7 @@ impl Lemma {
}
/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Positioned<T> {
/// The value was found in the left branch

View File

@ -275,3 +275,15 @@ fn test_custom_hashable_impl() {
assert_eq!(tree.count(), 10);
assert_eq!(tree.height(), 4);
}
#[cfg(feature = "serialization-serde")]
#[test]
fn test_serialize_proof_with_serde() {
extern crate serde_json;
let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
let tree = MerkleTree::from_vec(digest, values);
let proof = tree.gen_proof(vec![5]);
let serialized = serde_json::to_string(&proof).expect("serialize proof");
assert_eq!(proof, serde_json::from_str(&serialized).expect("deserialize proof"));
}