Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ members = [
"vm",
"vm/address",
"node",
"crypto"
"crypto",
"encoding"
]
1 change: 1 addition & 0 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ edition = "2018"
[dependencies]
blake2 = "0.8.1"
address = {path = "../vm/address"}
encoding = {path = "../encoding"}
libsecp256k1 = "0.2.1"
bls-signatures = "0.2.0"

Expand Down
8 changes: 4 additions & 4 deletions crypto/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use address::Error as AddressError;
use encoding::Error as EncodingError;
use secp256k1::Error as SecpError;
use std::error;
use std::fmt;
Expand Down Expand Up @@ -47,10 +48,9 @@ impl From<SecpError> for Error {
}
}

// TODO: Remove once cbor marshalling and unmarshalling implemented
impl From<String> for Error {
fn from(err: String) -> Error {
impl From<EncodingError> for Error {
fn from(err: EncodingError) -> Error {
// Pass error encountered in signer trait as module error type
Error::SigningError(err)
Error::SigningError(err.to_string())
}
}
17 changes: 2 additions & 15 deletions crypto/src/signature.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use super::errors::Error;
use address::{Address, Protocol};
use blake2::digest::{Input, VariableOutput};
use blake2::VarBlake2b;
use bls_signatures::{
hash as bls_hash, verify, PublicKey as BlsPubKey, Serialize, Signature as BlsSignature,
};
use encoding::blake2b_256;

use secp256k1::{recover, Message, RecoveryId, Signature as EcsdaSignature};

Expand Down Expand Up @@ -48,8 +47,7 @@ fn verify_bls_sig(data: Vec<u8>, pub_k: Vec<u8>, sig: Signature) -> bool {
/// returns true if a secp256k1 signature is valid
fn verify_secp256k1_sig(data: Vec<u8>, addr: Address, sig: Signature) -> bool {
// blake2b 256 hash
let mut hash = [0u8; 32];
blake2b_256(data, &mut hash);
let hash = blake2b_256(data);

// Ecrecover with hash and signature
let mut signature = [0u8; 65];
Expand Down Expand Up @@ -86,17 +84,6 @@ fn ecrecover(hash: &[u8; 32], signature: &[u8; 65]) -> Result<Address, Error> {
Ok(addr)
}

/// generates blake2b hash of 32 bytes
fn blake2b_256(ingest: Vec<u8>, hash: &mut [u8; 32]) {
let mut hasher = VarBlake2b::new(32).unwrap();
hasher.input(ingest);

hasher.variable_result(|res| {
// Copy result slice to vector return
hash[..32].clone_from_slice(res);
});
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
11 changes: 11 additions & 0 deletions encoding/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "encoding"
version = "0.1.0"
authors = ["ChainSafe Systems <info@chainsafe.io>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
blake2b_simd = "0.5.9"
serde_cbor = "0.10.2"
8 changes: 8 additions & 0 deletions encoding/src/cbor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use super::errors::Error;

pub trait Cbor {
fn unmarshal_cbor(bz: &[u8]) -> Result<Self, Error>
where
Self: Sized;
fn marshal_cbor(&self) -> Result<Vec<u8>, Error>;
}
80 changes: 80 additions & 0 deletions encoding/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::fmt;

/// Error type for encoding and decoding data through any Ferret supported protocol
///
/// This error will provide any details about the data which was attempted to be
/// encoded or decoded. The
///
/// Usage:
/// ```no_run
/// use encoding::{Error, CodecProtocol};
///
/// Error::Marshalling {
/// description: format!("{:?}", vec![0]),
/// protocol: CodecProtocol::Cbor,
/// };
/// Error::Unmarshalling {
/// description: format!("{:?}", vec![0]),
/// protocol: CodecProtocol::Cbor,
/// };
/// ```
#[derive(Debug, PartialEq)]
pub enum Error {
Unmarshalling {
description: String,
protocol: CodecProtocol,
},
Marshalling {
description: String,
protocol: CodecProtocol,
},
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Unmarshalling {
description,
protocol,
} => write!(
f,
"Could not decode in format {}: {}",
protocol, description
),
Error::Marshalling {
description,
protocol,
} => write!(
f,
"Could not encode in format {}: {}",
protocol, description
),
}
}
}

impl From<serde_cbor::error::Error> for Error {
fn from(err: serde_cbor::error::Error) -> Error {
Error::Marshalling {
description: err.to_string(),
protocol: CodecProtocol::Cbor,
}
}
}

/// CodecProtocol defines the protocol in which the data is encoded or decoded
///
/// This is used with the encoding errors, to detail the encoding protocol or any other
/// information about how the data was encoded or decoded
#[derive(Debug, PartialEq)]
pub enum CodecProtocol {
Cbor,
}

impl fmt::Display for CodecProtocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
CodecProtocol::Cbor => write!(f, "Cbor"),
}
}
}
59 changes: 59 additions & 0 deletions encoding/src/hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use blake2b_simd::Params;

/// generates blake2b hash with provided size
///
/// # Example
/// ```
/// use encoding::blake2b_variable;
///
/// let ingest: Vec<u8> = vec![];
/// let hash = blake2b_variable(ingest, 20);
/// assert_eq!(hash.len(), 20);
/// ```
pub fn blake2b_variable(ingest: Vec<u8>, size: usize) -> Vec<u8> {
let hash = Params::new()
.hash_length(size)
.to_state()
.update(&ingest)
.finalize();

hash.as_bytes().to_vec()
}

/// generates blake2b hash of fixed 32 bytes size
///
/// # Example
/// ```
/// use encoding::blake2b_256;
///
/// let ingest: Vec<u8> = vec![];
/// let hash = blake2b_256(ingest);
/// assert_eq!(hash.len(), 32);
/// ```
pub fn blake2b_256(ingest: Vec<u8>) -> [u8; 32] {
let digest = Params::new()
.hash_length(32)
.to_state()
.update(&ingest)
.finalize();

let mut ret = [0u8; 32];
ret.clone_from_slice(digest.as_bytes());
ret
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn hash_length() {
let ingest = vec![1, 4, 2, 3];
let hash = blake2b_variable(ingest.clone(), 8);
assert_eq!(hash.len(), 8);
let hash = blake2b_variable(ingest.clone(), 20);
assert_eq!(hash.len(), 20);
let hash = blake2b_variable(ingest.clone(), 32);
assert_eq!(hash.len(), 32);
}
}
7 changes: 7 additions & 0 deletions encoding/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod cbor;
mod errors;
mod hash;

pub use cbor::*;
pub use errors::*;
pub use hash::*;
2 changes: 2 additions & 0 deletions vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ cid = "0.3.1"
num-bigint = "0.2.3"
crypto = {path = "../crypto"}
address = {path = "./address"}
encoding = {path = "../encoding"}


3 changes: 2 additions & 1 deletion vm/address/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ num-traits = "0.2"
num-derive = "0.2"
data-encoding = "2.1.2"
data-encoding-macro = "0.1.7"
blake2 = "0.8.1"
leb128 = "0.2.1"
encoding = {path = "../../encoding"}
serde_cbor = "0.10.2"
52 changes: 16 additions & 36 deletions vm/address/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ pub use self::errors::Error;
pub use self::network::Network;
pub use self::protocol::Protocol;

use blake2::digest::{Input, VariableOutput};
use blake2::VarBlake2b;
use data_encoding::Encoding;
use data_encoding_macro::{internal_new_encoding, new_encoding};
use encoding::{blake2b_variable, Cbor, CodecProtocol, Error as EncodingError};
use leb128;

/// defines the encoder for base32 encoding with the provided string with no padding
Expand All @@ -26,7 +25,7 @@ const TESTNET_PREFIX: &str = "t";

/// Address is the struct that defines the protocol and data payload conversion from either
/// a public key or value
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub struct Address {
protocol: Protocol,
payload: Vec<u8>,
Expand Down Expand Up @@ -168,25 +167,22 @@ impl Address {
None => encode(self, Network::Testnet),
}
}
}

// Marshalling and unmarshalling
pub fn unmarshall_cbor(&mut self, _bz: &mut [u8]) -> Result<(), String> {
// TODO
Err("Unmarshall is unimplemented".to_owned())
}
pub fn marshall_cbor(&self) -> Result<Vec<u8>, String> {
// TODO
Err("Marshall is unimplemented".to_owned())
}

// JSON Marshalling and unmarshalling
pub fn unmarshall_json(&mut self, _bz: &mut [u8]) -> Result<(), String> {
impl Cbor for Address {
fn unmarshal_cbor(_bz: &[u8]) -> Result<Self, EncodingError> {
// TODO
Err("JSON unmarshall is unimplemented".to_owned())
Err(EncodingError::Unmarshalling {
description: "Not Implemented".to_string(),
protocol: CodecProtocol::Cbor,
})
}
pub fn marshall_json(&self) -> Result<Vec<u8>, String> {
fn marshal_cbor(&self) -> Result<Vec<u8>, EncodingError> {
// TODO
Err("JSON marshall is unimplemented".to_owned())
Err(EncodingError::Marshalling {
description: format!("Not implemented, data: {:?}", self),
protocol: CodecProtocol::Cbor,
})
}
}

Expand Down Expand Up @@ -224,7 +220,7 @@ fn encode(addr: &Address, network: Network) -> String {

/// Checksum calculates the 4 byte checksum hash
pub fn checksum(ingest: Vec<u8>) -> Vec<u8> {
hash(ingest, CHECKSUM_HASH_LEN)
blake2b_variable(ingest, CHECKSUM_HASH_LEN)
}

/// Validates the checksum against the ingest data
Expand All @@ -235,21 +231,5 @@ pub fn validate_checksum(ingest: Vec<u8>, expect: Vec<u8>) -> bool {

/// Returns an address hash for given data
fn address_hash(ingest: Vec<u8>) -> Vec<u8> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this actually used for?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to create the 20 byte hash used as the address for secp256k1 and actor protocols

hash(ingest, PAYLOAD_HASH_LEN)
}

/// generates blake2b hash with provided size
fn hash(ingest: Vec<u8>, size: usize) -> Vec<u8> {
let mut hasher = VarBlake2b::new(size).unwrap();
hasher.input(ingest);

// allocate hash result vector
let mut result: Vec<u8> = vec![0; size];

hasher.variable_result(|res| {
// Copy result slice to vector return
result[..size].clone_from_slice(res);
});

result
blake2b_variable(ingest, PAYLOAD_HASH_LEN)
}
2 changes: 1 addition & 1 deletion vm/address/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use num_traits::FromPrimitive;
use std::fmt;

/// Protocol defines the addressing protocol used to derive data to an address
#[derive(PartialEq, Copy, Clone, FromPrimitive)]
#[derive(PartialEq, Copy, Clone, FromPrimitive, Debug)]
pub enum Protocol {
// ID protocol addressing
ID = 0,
Expand Down
2 changes: 1 addition & 1 deletion vm/address/tests/address_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn test_address(addr: Address, protocol: Protocol, expected: &'static str) {
let from_bytes = Address::from_bytes(decoded.to_bytes()).unwrap();
assert!(decoded == from_bytes);

// TODO: test JSON/cbor encoding and decoding
// TODO: test cbor encoding and decoding
}

#[test]
Expand Down
Loading