mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-18 04:21:22 +00:00
Clean up directory structure (#426)
* Remove unused circular-buffer crate * Move transports into subdirectory * Move misc into subdirectory * Move stores into subdirectory * Move multiplexers * Move protocols * Move libp2p top layer * Fix Test: skip doctest if secio isn't enabled
This commit is contained in:
committed by
GitHub
parent
f5ce93c730
commit
2ea49718f3
63
misc/multihash/src/errors.rs
Normal file
63
misc/multihash/src/errors.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use std::{fmt, error};
|
||||
|
||||
/// Error that can happen when encoding some bytes into a multihash.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum EncodeError {
|
||||
/// The requested hash algorithm isn't supported by this library.
|
||||
UnsupportedType,
|
||||
}
|
||||
|
||||
impl fmt::Display for EncodeError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
EncodeError::UnsupportedType => write!(f, "This type is not supported yet"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for EncodeError {
|
||||
}
|
||||
|
||||
/// Error that can happen when decoding some bytes.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum DecodeError {
|
||||
/// The input doesn't have a correct length.
|
||||
BadInputLength,
|
||||
/// The code of the hashing algorithm is incorrect.
|
||||
UnknownCode,
|
||||
}
|
||||
|
||||
impl fmt::Display for DecodeError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
DecodeError::BadInputLength => write!(f, "Not matching input length"),
|
||||
DecodeError::UnknownCode => write!(f, "Found unknown code"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for DecodeError {
|
||||
}
|
||||
|
||||
/// Error that can happen when decoding some bytes.
|
||||
///
|
||||
/// Same as `DecodeError`, but allows retreiving the data whose decoding was attempted.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DecodeOwnedError {
|
||||
/// The error.
|
||||
pub error: DecodeError,
|
||||
/// The data whose decoding was attempted.
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl fmt::Display for DecodeOwnedError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.error)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for DecodeOwnedError {
|
||||
}
|
93
misc/multihash/src/hashes.rs
Normal file
93
misc/multihash/src/hashes.rs
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
/// List of types currently supported in the multihash spec.
|
||||
///
|
||||
/// Not all hash types are supported by this library.
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)]
|
||||
pub enum Hash {
|
||||
/// SHA-1 (20-byte hash size)
|
||||
SHA1,
|
||||
/// SHA-256 (32-byte hash size)
|
||||
SHA2256,
|
||||
/// SHA-512 (64-byte hash size)
|
||||
SHA2512,
|
||||
/// SHA3-512 (64-byte hash size)
|
||||
SHA3512,
|
||||
/// SHA3-384 (48-byte hash size)
|
||||
SHA3384,
|
||||
/// SHA3-256 (32-byte hash size)
|
||||
SHA3256,
|
||||
/// SHA3-224 (28-byte hash size)
|
||||
SHA3224,
|
||||
/// Keccak-224 (28-byte hash size)
|
||||
Keccak224,
|
||||
/// Keccak-256 (32-byte hash size)
|
||||
Keccak256,
|
||||
/// Keccak-384 (48-byte hash size)
|
||||
Keccak384,
|
||||
/// Keccak-512 (64-byte hash size)
|
||||
Keccak512,
|
||||
/// Encoding unsupported
|
||||
Blake2b,
|
||||
/// Encoding unsupported
|
||||
Blake2s,
|
||||
}
|
||||
|
||||
impl Hash {
|
||||
/// Get the corresponding hash code.
|
||||
pub fn code(&self) -> u8 {
|
||||
match *self {
|
||||
Hash::SHA1 => 0x11,
|
||||
Hash::SHA2256 => 0x12,
|
||||
Hash::SHA2512 => 0x13,
|
||||
Hash::SHA3224 => 0x17,
|
||||
Hash::SHA3256 => 0x16,
|
||||
Hash::SHA3384 => 0x15,
|
||||
Hash::SHA3512 => 0x14,
|
||||
Hash::Keccak224 => 0x1A,
|
||||
Hash::Keccak256 => 0x1B,
|
||||
Hash::Keccak384 => 0x1C,
|
||||
Hash::Keccak512 => 0x1D,
|
||||
Hash::Blake2b => 0x40,
|
||||
Hash::Blake2s => 0x41,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the hash length in bytes.
|
||||
pub fn size(&self) -> u8 {
|
||||
match *self {
|
||||
Hash::SHA1 => 20,
|
||||
Hash::SHA2256 => 32,
|
||||
Hash::SHA2512 => 64,
|
||||
Hash::SHA3224 => 28,
|
||||
Hash::SHA3256 => 32,
|
||||
Hash::SHA3384 => 48,
|
||||
Hash::SHA3512 => 64,
|
||||
Hash::Keccak224 => 28,
|
||||
Hash::Keccak256 => 32,
|
||||
Hash::Keccak384 => 48,
|
||||
Hash::Keccak512 => 64,
|
||||
Hash::Blake2b => 64,
|
||||
Hash::Blake2s => 32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the algorithm corresponding to a code, or `None` if no algorith is matching.
|
||||
pub fn from_code(code: u8) -> Option<Hash> {
|
||||
Some(match code {
|
||||
0x11 => Hash::SHA1,
|
||||
0x12 => Hash::SHA2256,
|
||||
0x13 => Hash::SHA2512,
|
||||
0x14 => Hash::SHA3512,
|
||||
0x15 => Hash::SHA3384,
|
||||
0x16 => Hash::SHA3256,
|
||||
0x17 => Hash::SHA3224,
|
||||
0x1A => Hash::Keccak224,
|
||||
0x1B => Hash::Keccak256,
|
||||
0x1C => Hash::Keccak384,
|
||||
0x1D => Hash::Keccak512,
|
||||
0x40 => Hash::Blake2b,
|
||||
0x41 => Hash::Blake2s,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
239
misc/multihash/src/lib.rs
Normal file
239
misc/multihash/src/lib.rs
Normal file
@ -0,0 +1,239 @@
|
||||
//! # Multihash
|
||||
//!
|
||||
//! Implementation of [multihash](https://github.com/multiformats/multihash) in Rust.
|
||||
//!
|
||||
//! A `Multihash` is a structure that contains a hashing algorithm, plus some hashed data.
|
||||
//! A `MultihashRef` is the same as a `Multihash`, except that it doesn't own its data.
|
||||
//!
|
||||
|
||||
extern crate sha1;
|
||||
extern crate sha2;
|
||||
extern crate tiny_keccak;
|
||||
|
||||
mod errors;
|
||||
mod hashes;
|
||||
|
||||
use std::fmt::Write;
|
||||
use sha2::Digest;
|
||||
use tiny_keccak::Keccak;
|
||||
|
||||
pub use hashes::Hash;
|
||||
pub use errors::{EncodeError, DecodeError, DecodeOwnedError};
|
||||
|
||||
// Helper macro for encoding input into output using sha1, sha2 or tiny_keccak
|
||||
macro_rules! encode {
|
||||
(sha1, Sha1, $input:expr, $output:expr) => ({
|
||||
let mut hasher = sha1::Sha1::new();
|
||||
hasher.update($input);
|
||||
$output.copy_from_slice(&hasher.digest().bytes());
|
||||
});
|
||||
(sha2, $algorithm:ident, $input:expr, $output:expr) => ({
|
||||
let mut hasher = sha2::$algorithm::default();
|
||||
hasher.input($input);
|
||||
$output.copy_from_slice(hasher.result().as_ref());
|
||||
});
|
||||
(tiny, $constructor:ident, $input:expr, $output:expr) => ({
|
||||
let mut kec = Keccak::$constructor();
|
||||
kec.update($input);
|
||||
kec.finalize($output);
|
||||
});
|
||||
}
|
||||
|
||||
// And another one to keep the matching DRY
|
||||
macro_rules! match_encoder {
|
||||
($hash:ident for ($input:expr, $output:expr) {
|
||||
$( $hashtype:ident => $lib:ident :: $method:ident, )*
|
||||
}) => ({
|
||||
match $hash {
|
||||
$(
|
||||
Hash::$hashtype => encode!($lib, $method, $input, $output),
|
||||
)*
|
||||
|
||||
_ => return Err(EncodeError::UnsupportedType)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Encodes data into a multihash.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Will return an error if the specified hash type is not supported. See the docs for `Hash`
|
||||
/// to see what is supported.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use multihash::{encode, Hash};
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// encode(Hash::SHA2256, b"hello world").unwrap().into_bytes(),
|
||||
/// vec![18, 32, 185, 77, 39, 185, 147, 77, 62, 8, 165, 46, 82, 215, 218, 125, 171, 250, 196,
|
||||
/// 132, 239, 227, 122, 83, 128, 238, 144, 136, 247, 172, 226, 239, 205, 233]
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
pub fn encode(hash: Hash, input: &[u8]) -> Result<Multihash, EncodeError> {
|
||||
let size = hash.size();
|
||||
let mut output = Vec::new();
|
||||
output.resize(2 + size as usize, 0);
|
||||
output[0] = hash.code();
|
||||
output[1] = size;
|
||||
|
||||
match_encoder!(hash for (input, &mut output[2..]) {
|
||||
SHA1 => sha1::Sha1,
|
||||
SHA2256 => sha2::Sha256,
|
||||
SHA2512 => sha2::Sha512,
|
||||
SHA3224 => tiny::new_sha3_224,
|
||||
SHA3256 => tiny::new_sha3_256,
|
||||
SHA3384 => tiny::new_sha3_384,
|
||||
SHA3512 => tiny::new_sha3_512,
|
||||
Keccak224 => tiny::new_keccak224,
|
||||
Keccak256 => tiny::new_keccak256,
|
||||
Keccak384 => tiny::new_keccak384,
|
||||
Keccak512 => tiny::new_keccak512,
|
||||
});
|
||||
|
||||
Ok(Multihash { bytes: output })
|
||||
}
|
||||
|
||||
/// Represents a valid multihash.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Multihash {
|
||||
bytes: Vec<u8>
|
||||
}
|
||||
|
||||
impl Multihash {
|
||||
/// Verifies whether `bytes` contains a valid multihash, and if so returns a `Multihash`.
|
||||
#[inline]
|
||||
pub fn from_bytes(bytes: Vec<u8>) -> Result<Multihash, DecodeOwnedError> {
|
||||
if let Err(err) = MultihashRef::from_slice(&bytes) {
|
||||
return Err(DecodeOwnedError {
|
||||
error: err,
|
||||
data: bytes,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Multihash { bytes })
|
||||
}
|
||||
|
||||
/// Returns the bytes representation of the multihash.
|
||||
#[inline]
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
self.bytes
|
||||
}
|
||||
|
||||
/// Returns the bytes representation of this multihash.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
}
|
||||
|
||||
/// Builds a `MultihashRef` corresponding to this `Multihash`.
|
||||
#[inline]
|
||||
pub fn as_ref(&self) -> MultihashRef {
|
||||
MultihashRef { bytes: &self.bytes }
|
||||
}
|
||||
|
||||
/// Returns which hashing algorithm is used in this multihash.
|
||||
#[inline]
|
||||
pub fn algorithm(&self) -> Hash {
|
||||
self.as_ref().algorithm()
|
||||
}
|
||||
|
||||
/// Returns the hashed data.
|
||||
#[inline]
|
||||
pub fn digest(&self) -> &[u8] {
|
||||
self.as_ref().digest()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<MultihashRef<'a>> for Multihash {
|
||||
#[inline]
|
||||
fn eq(&self, other: &MultihashRef<'a>) -> bool {
|
||||
&*self.bytes == other.bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a valid multihash.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct MultihashRef<'a> {
|
||||
bytes: &'a [u8]
|
||||
}
|
||||
|
||||
impl<'a> MultihashRef<'a> {
|
||||
/// Verifies whether `bytes` contains a valid multihash, and if so returns a `MultihashRef`.
|
||||
pub fn from_slice(input: &'a [u8]) -> Result<MultihashRef<'a>, DecodeError> {
|
||||
if input.is_empty() {
|
||||
return Err(DecodeError::BadInputLength);
|
||||
}
|
||||
|
||||
// TODO: note that `input[0]` and `input[1]` and technically variable-length integers,
|
||||
// but there's no hashing algorithm implemented in this crate whose code or digest length
|
||||
// is superior to 128
|
||||
let code = input[0];
|
||||
|
||||
// TODO: see comment just above about varints
|
||||
if input[0] >= 128 || input[1] >= 128 {
|
||||
return Err(DecodeError::BadInputLength);
|
||||
}
|
||||
|
||||
let alg = Hash::from_code(code).ok_or(DecodeError::UnknownCode)?;
|
||||
let hash_len = alg.size() as usize;
|
||||
|
||||
// length of input should be exactly hash_len + 2
|
||||
if input.len() != hash_len + 2 {
|
||||
return Err(DecodeError::BadInputLength);
|
||||
}
|
||||
|
||||
if input[1] as usize != hash_len {
|
||||
return Err(DecodeError::BadInputLength);
|
||||
}
|
||||
|
||||
Ok(MultihashRef { bytes: input })
|
||||
}
|
||||
|
||||
/// Returns which hashing algorithm is used in this multihash.
|
||||
#[inline]
|
||||
pub fn algorithm(&self) -> Hash {
|
||||
Hash::from_code(self.bytes[0]).expect("multihash is known to be valid")
|
||||
}
|
||||
|
||||
/// Returns the hashed data.
|
||||
#[inline]
|
||||
pub fn digest(&self) -> &'a [u8] {
|
||||
&self.bytes[2..]
|
||||
}
|
||||
|
||||
/// Builds a `Multihash` that owns the data.
|
||||
///
|
||||
/// This operation allocates.
|
||||
#[inline]
|
||||
pub fn into_owned(&self) -> Multihash {
|
||||
Multihash { bytes: self.bytes.to_owned() }
|
||||
}
|
||||
|
||||
/// Returns the bytes representation of this multihash.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &'a [u8] {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<Multihash> for MultihashRef<'a> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Multihash) -> bool {
|
||||
self.bytes == &*other.bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert bytes to a hex representation
|
||||
pub fn to_hex(bytes: &[u8]) -> String {
|
||||
let mut hex = String::with_capacity(bytes.len() * 2);
|
||||
|
||||
for byte in bytes {
|
||||
write!(hex, "{:02x}", byte).expect("Can't fail on writing to string");
|
||||
}
|
||||
|
||||
hex
|
||||
}
|
Reference in New Issue
Block a user