From 42cb9c1ff9edc8b2ce5993a8256c2a146b68ae5c Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 12 Sep 2019 03:46:39 -0700 Subject: [PATCH] Add a `Sha256dChecksum` type for truncated double SHA256. --- zebra-chain/Cargo.toml | 1 + zebra-chain/src/types.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 20580e65..0b03b9e0 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +sha2 = "0.8" diff --git a/zebra-chain/src/types.rs b/zebra-chain/src/types.rs index 090454af..9a33fe7b 100644 --- a/zebra-chain/src/types.rs +++ b/zebra-chain/src/types.rs @@ -1,5 +1,20 @@ //! Newtype wrappers for primitive data types with semantic meaning. +/// A 4-byte checksum using truncated double SHA256. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct Sha256dChecksum(pub [u8; 4]); + +impl<'a> From<&'a [u8]> for Sha256dChecksum { + fn from(bytes: &'a [u8]) -> Self { + use sha2::{Sha256, Digest}; + let hash1 = Sha256::digest(bytes); + let hash2 = Sha256::digest(&hash1); + let mut checksum = [0u8; 4]; + checksum[0..4].copy_from_slice(&hash2[0..4]); + Self(checksum) + } +} + /// A u32 which represents a block height value. pub struct BlockHeight(pub u32); @@ -34,3 +49,17 @@ pub enum InventoryType { /// Inventory Vector pub struct InventoryVector(pub InventoryType, pub [u8; 32]); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sha256d_checksum() { + // https://en.bitcoin.it/wiki/Protocol_documentation#Hashes + let input = b"hello"; + let checksum = Sha256dChecksum::from(&input[..]); + let expected = Sha256dChecksum([0x95, 0x95, 0xc9, 0xdf]); + assert_eq!(checksum, expected); + } +} \ No newline at end of file