From 3b95cc0ba3d7b06769251643c65595cb5e66b371 Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Tue, 25 Jun 2024 12:38:35 +0100 Subject: [PATCH] crypto/encoding: swap dependency direction --- CHANGELOG.md | 1 + Cargo.lock | 3 +- Cargo.toml | 18 +++++ crypto/Cargo.toml | 3 + crypto/src/hash.rs | 6 +- crypto/src/hash/encoding.rs | 140 +++++++++++++++++++++++++++++++++ crypto/src/signature.rs | 35 +++++++++ tezos-encoding/Cargo.toml | 7 +- tezos-encoding/src/enc.rs | 47 ----------- tezos-encoding/src/encoding.rs | 52 +----------- tezos-encoding/src/lib.rs | 2 - tezos-encoding/src/nom.rs | 60 +------------- 12 files changed, 207 insertions(+), 167 deletions(-) create mode 100644 crypto/src/hash/encoding.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eef2a73b3..852562f83c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ parameterized by the lifetime of the input byte slice. - Update `blst` dependency to `0.3.12` to improve RISC-V compatibility. - Update `num-bigint` dependency to `0.4` to improve WASM compatibility. - Minimum supported rust version bumped to `1.64`. +- `tezos_crypto_rs` now depends on `tezos_data_encoding`, rather than vice-versa. ### Deprecated diff --git a/Cargo.lock b/Cargo.lock index 04d3a78a16..59c51d99ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,6 +1000,7 @@ dependencies = [ "ed25519-dalek", "hex", "libsecp256k1", + "nom", "num-bigint", "num-traits", "p256", @@ -1009,6 +1010,7 @@ dependencies = [ "serde_json", "strum", "strum_macros", + "tezos_data_encoding", "thiserror", "zeroize", ] @@ -1026,7 +1028,6 @@ dependencies = [ "num-traits", "serde", "serde_json", - "tezos_crypto_rs", "tezos_data_encoding_derive", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index d1cc3e3fcb..6a4f5187eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,24 @@ members = [ "tezos-encoding-derive", ] +[workspace.dependencies.tezos_data_encoding] +version = "0.5.2" +path = "./tezos-encoding" +default-features = false + +[workspace.dependencies.tezos_data_encoding_derive] +version = "0.5.2" +path = "./tezos-encoding-derive" +default-features = false + +[workspace.dependencies.tezos_crypto_rs] +version = "0.5.2" +path = "./crypto" +default-features = false + +[workspace.dependencies.nom] +version = "7.1" + [profile.fuzz] inherits = "release" opt-level = 3 diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index c2529fbf58..ff48a5b132 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -31,6 +31,9 @@ blst = { version = "0.3.12", optional = true } proptest = { version = "1.1", optional = true } +tezos_data_encoding.workspace = true +nom.workspace = true + [dev-dependencies] serde_json = "1.0" diff --git a/crypto/src/hash.rs b/crypto/src/hash.rs index b1c1660739..64a72199e1 100644 --- a/crypto/src/hash.rs +++ b/crypto/src/hash.rs @@ -13,6 +13,8 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use zeroize::Zeroize; +mod encoding; + const CRYPTO_KEY_SIZE: usize = 32; mod prefix_bytes { @@ -339,7 +341,9 @@ unknown_sig!(Secp256k1Signature); unknown_sig!(P256Signature); /// Note: see Tezos ocaml lib_crypto/base58.ml -#[derive(Debug, Copy, Clone, PartialEq, Eq, strum_macros::AsRefStr)] +#[derive( + Debug, Copy, Clone, PartialEq, Eq, strum_macros::AsRefStr, strum_macros::IntoStaticStr, +)] pub enum HashType { // "\087\082\000" (* Net(15) *) ChainId, diff --git a/crypto/src/hash/encoding.rs b/crypto/src/hash/encoding.rs new file mode 100644 index 0000000000..f8b5d77e1e --- /dev/null +++ b/crypto/src/hash/encoding.rs @@ -0,0 +1,140 @@ +// Copyright (c) SimpleStaking, Viable Systems, Nomadic Labs and Tezedge Contributors +// SPDX-CopyrightText: 2022-2024 TriliTech +// +// SPDX-License-Identifier: MIT + +use super::*; +use tezos_data_encoding::enc::{BinResult, BinWriter}; +use tezos_data_encoding::encoding::{Encoding, HasEncoding}; +use tezos_data_encoding::nom::{NomReader, NomResult}; + +macro_rules! encode_hash { + ($hash_name:ty) => { + impl BinWriter for $hash_name { + fn bin_write(&self, out: &mut Vec) -> BinResult { + use tezos_data_encoding::enc::*; + + put_bytes(self.as_ref(), out); + Ok(()) + } + } + }; +} + +encode_hash!(ChainId); +encode_hash!(BlockHash); +encode_hash!(BlockMetadataHash); +encode_hash!(BlockPayloadHash); +encode_hash!(OperationHash); +encode_hash!(OperationListListHash); +encode_hash!(OperationMetadataHash); +encode_hash!(OperationMetadataListListHash); +encode_hash!(ContextHash); +encode_hash!(ProtocolHash); +encode_hash!(ContractKt1Hash); +encode_hash!(ContractTz1Hash); +encode_hash!(ContractTz2Hash); +encode_hash!(ContractTz3Hash); +encode_hash!(ContractTz4Hash); +encode_hash!(CryptoboxPublicKeyHash); +encode_hash!(PublicKeyEd25519); +encode_hash!(PublicKeySecp256k1); +encode_hash!(PublicKeyP256); +encode_hash!(PublicKeyBls); +encode_hash!(SecretKeyEd25519); +encode_hash!(SecretKeyBls); +encode_hash!(UnknownSignature); +encode_hash!(Ed25519Signature); +encode_hash!(Secp256k1Signature); +encode_hash!(P256Signature); +encode_hash!(BlsSignature); +encode_hash!(NonceHash); +encode_hash!(SmartRollupHash); + +macro_rules! hash_nom_reader { + ($hash_name:ident) => { + impl<'a> NomReader<'a> for $hash_name { + #[inline(always)] + fn nom_read(input: &[u8]) -> NomResult { + use nom::{bytes::complete::take, combinator::map}; + + map(take(Self::hash_size()), |bytes| { + Self::try_from_bytes(bytes).unwrap() + })(input) + } + } + }; +} + +hash_nom_reader!(ChainId); +hash_nom_reader!(BlockHash); +hash_nom_reader!(BlockMetadataHash); +hash_nom_reader!(BlockPayloadHash); +hash_nom_reader!(OperationHash); +hash_nom_reader!(OperationListListHash); +hash_nom_reader!(OperationMetadataHash); +hash_nom_reader!(OperationMetadataListListHash); +hash_nom_reader!(ContextHash); +hash_nom_reader!(ProtocolHash); +hash_nom_reader!(ContractKt1Hash); +hash_nom_reader!(ContractTz1Hash); +hash_nom_reader!(ContractTz2Hash); +hash_nom_reader!(ContractTz3Hash); +hash_nom_reader!(ContractTz4Hash); +hash_nom_reader!(CryptoboxPublicKeyHash); +hash_nom_reader!(PublicKeyEd25519); +hash_nom_reader!(PublicKeySecp256k1); +hash_nom_reader!(PublicKeyP256); +hash_nom_reader!(PublicKeyBls); +hash_nom_reader!(SecretKeyEd25519); +hash_nom_reader!(SecretKeyBls); +hash_nom_reader!(UnknownSignature); +hash_nom_reader!(Ed25519Signature); +hash_nom_reader!(Secp256k1Signature); +hash_nom_reader!(P256Signature); +hash_nom_reader!(BlsSignature); +hash_nom_reader!(NonceHash); +hash_nom_reader!(SmartRollupHash); + +macro_rules! hash_has_encoding { + ($hash_name:ident, $enc_ref_name:ident) => { + impl HasEncoding for $hash_name { + fn encoding() -> Encoding { + Encoding::Hash($hash_name::hash_type().into()) + } + } + }; +} + +hash_has_encoding!(ChainId, CHAIN_ID); +hash_has_encoding!(BlockHash, BLOCK_HASH); +hash_has_encoding!(BlockMetadataHash, BLOCK_METADATA_HASH); +hash_has_encoding!(BlockPayloadHash, BLOCK_PAYLOAD_HASH); +hash_has_encoding!(OperationHash, OPERATION_HASH); +hash_has_encoding!(OperationListListHash, OPERATION_LIST_LIST_HASH); +hash_has_encoding!(OperationMetadataHash, OPERATION_METADATA_HASH); +hash_has_encoding!( + OperationMetadataListListHash, + OPERATION_METADATA_LIST_LIST_HASH +); +hash_has_encoding!(ContextHash, CONTEXT_HASH); +hash_has_encoding!(ProtocolHash, PROTOCOL_HASH); +hash_has_encoding!(ContractKt1Hash, CONTRACT_KT1HASH); +hash_has_encoding!(ContractTz1Hash, CONTRACT_TZ1HASH); +hash_has_encoding!(ContractTz2Hash, CONTRACT_TZ2HASH); +hash_has_encoding!(ContractTz3Hash, CONTRACT_TZ3HASH); +hash_has_encoding!(ContractTz4Hash, CONTRACT_TZ4HASH); +hash_has_encoding!(CryptoboxPublicKeyHash, CRYPTOBOX_PUBLIC_KEY_HASH); +hash_has_encoding!(PublicKeyEd25519, PUBLIC_KEY_ED25519); +hash_has_encoding!(PublicKeySecp256k1, PUBLIC_KEY_SECP256K1); +hash_has_encoding!(PublicKeyP256, PUBLIC_KEY_P256); +hash_has_encoding!(PublicKeyBls, PUBLIC_KEY_BLS); +hash_has_encoding!(SecretKeyEd25519, SECRET_KEY_ED25519); +hash_has_encoding!(SecretKeyBls, SECRET_KEY_BLS); +hash_has_encoding!(UnknownSignature, UNKNOWN_SIGNATURE); +hash_has_encoding!(Ed25519Signature, ED25519_SIGNATURE_HASH); +hash_has_encoding!(Secp256k1Signature, SECP256K1_SIGNATURE_HASH); +hash_has_encoding!(P256Signature, P256_SIGNATURE_HASH); +hash_has_encoding!(BlsSignature, BLS_SIGNATURE_HASH); +hash_has_encoding!(NonceHash, NONCE_HASH); +hash_has_encoding!(SmartRollupHash, SMART_ROLLUP_HASH); diff --git a/crypto/src/signature.rs b/crypto/src/signature.rs index 832e018357..01d3cb8f24 100644 --- a/crypto/src/signature.rs +++ b/crypto/src/signature.rs @@ -14,7 +14,13 @@ use crate::hash::{ BlsSignature, Ed25519Signature, FromBytesError, HashTrait, HashType, P256Signature, Secp256k1Signature, UnknownSignature, }; +use nom::Err; use serde::{Deserialize, Serialize}; +use tezos_data_encoding::enc::{BinResult, BinWriter}; +use tezos_data_encoding::encoding::{Encoding, HasEncoding}; +use tezos_data_encoding::nom::error::BoundedEncodingKind; +use tezos_data_encoding::nom::error::DecodeError; +use tezos_data_encoding::nom::{NomReader, NomResult}; use thiserror::Error; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] @@ -201,6 +207,35 @@ impl TryFrom for UnknownSignature { } } +impl BinWriter for Signature { + fn bin_write(&self, out: &mut Vec) -> BinResult { + use tezos_data_encoding::enc::*; + + dynamic(bytes)(self, out) + } +} +impl HasEncoding for Signature { + fn encoding() -> Encoding { + Encoding::Custom + } +} + +impl<'a> NomReader<'a> for Signature { + fn nom_read(input: &'a [u8]) -> NomResult<'a, Self> { + use tezos_data_encoding::nom::*; + + let (rest, v) = dynamic(bytes)(input)?; + if let Ok(v) = Self::try_from(v) { + Ok((rest, v)) + } else { + Err(Err::Error(DecodeError::limit( + input, + BoundedEncodingKind::Signature, + ))) + } + } +} + #[cfg(test)] mod test { #[test] diff --git a/tezos-encoding/Cargo.toml b/tezos-encoding/Cargo.toml index a47dc631dc..b1ed9f9cff 100644 --- a/tezos-encoding/Cargo.toml +++ b/tezos-encoding/Cargo.toml @@ -17,15 +17,10 @@ hex = "0.4" num-bigint = { version = "0.4", default-features = false } num-traits = "0.2.8" serde = { version = "1.0", features = ["derive"] } -nom = "7.1" +nom.workspace = true bitvec = "1.0" lazy_static = "1.4" -[dependencies.tezos_crypto_rs] -path = "../crypto" -version = "0.5.2" -default-features = false - [dependencies.tezos_data_encoding_derive] path = "../tezos-encoding-derive" version = "0.5.2" diff --git a/tezos-encoding/src/enc.rs b/tezos-encoding/src/enc.rs index 78ffd483a4..fa1a12a924 100644 --- a/tezos-encoding/src/enc.rs +++ b/tezos-encoding/src/enc.rs @@ -318,53 +318,6 @@ mod integers { pub use integers::*; -macro_rules! encode_hash { - ($hash_name:ty) => { - impl BinWriter for $hash_name { - fn bin_write(&self, out: &mut Vec) -> BinResult { - put_bytes(self.as_ref(), out); - Ok(()) - } - } - }; -} - -encode_hash!(crypto::hash::ChainId); -encode_hash!(crypto::hash::BlockHash); -encode_hash!(crypto::hash::BlockMetadataHash); -encode_hash!(crypto::hash::BlockPayloadHash); -encode_hash!(crypto::hash::OperationHash); -encode_hash!(crypto::hash::OperationListListHash); -encode_hash!(crypto::hash::OperationMetadataHash); -encode_hash!(crypto::hash::OperationMetadataListListHash); -encode_hash!(crypto::hash::ContextHash); -encode_hash!(crypto::hash::ProtocolHash); -encode_hash!(crypto::hash::ContractKt1Hash); -encode_hash!(crypto::hash::ContractTz1Hash); -encode_hash!(crypto::hash::ContractTz2Hash); -encode_hash!(crypto::hash::ContractTz3Hash); -encode_hash!(crypto::hash::ContractTz4Hash); -encode_hash!(crypto::hash::CryptoboxPublicKeyHash); -encode_hash!(crypto::hash::PublicKeyEd25519); -encode_hash!(crypto::hash::PublicKeySecp256k1); -encode_hash!(crypto::hash::PublicKeyP256); -encode_hash!(crypto::hash::PublicKeyBls); -encode_hash!(crypto::hash::SecretKeyEd25519); -encode_hash!(crypto::hash::SecretKeyBls); -encode_hash!(crypto::hash::UnknownSignature); -encode_hash!(crypto::hash::Ed25519Signature); -encode_hash!(crypto::hash::Secp256k1Signature); -encode_hash!(crypto::hash::P256Signature); -encode_hash!(crypto::hash::BlsSignature); -encode_hash!(crypto::hash::NonceHash); -encode_hash!(crypto::hash::SmartRollupHash); - -impl BinWriter for crypto::signature::Signature { - fn bin_write(&self, out: &mut Vec) -> BinResult { - dynamic(bytes)(self, out) - } -} - impl BinWriter for Mutez { fn bin_write(&self, out: &mut Vec) -> BinResult { n_bignum(self.0.magnitude(), out) diff --git a/tezos-encoding/src/encoding.rs b/tezos-encoding/src/encoding.rs index 5ff8e68004..49c24ce788 100644 --- a/tezos-encoding/src/encoding.rs +++ b/tezos-encoding/src/encoding.rs @@ -4,7 +4,6 @@ //! Schema used for serialization and deserialization. -use crypto::hash::{HashTrait, HashType}; use std::collections::HashMap; pub use tezos_data_encoding_derive::HasEncoding; @@ -215,7 +214,7 @@ pub enum Encoding { Greedy(Box), /// Decode various types of hashes. Hash has it's own predefined length and prefix. /// This is controller by a hash implementation. - Hash(HashType), + Hash(&'static str), /// Timestamp encoding. /// - encoded as RFC 3339 in json /// - encoded as [Encoding::Int64] in binary @@ -303,55 +302,6 @@ pub trait HasEncoding { fn encoding() -> Encoding; } -macro_rules! hash_has_encoding { - ($hash_name:ident, $enc_ref_name:ident) => { - impl HasEncoding for crypto::hash::$hash_name { - fn encoding() -> Encoding { - Encoding::Hash(crypto::hash::$hash_name::hash_type()) - } - } - }; -} - -hash_has_encoding!(ChainId, CHAIN_ID); -hash_has_encoding!(BlockHash, BLOCK_HASH); -hash_has_encoding!(BlockMetadataHash, BLOCK_METADATA_HASH); -hash_has_encoding!(BlockPayloadHash, BLOCK_PAYLOAD_HASH); -hash_has_encoding!(OperationHash, OPERATION_HASH); -hash_has_encoding!(OperationListListHash, OPERATION_LIST_LIST_HASH); -hash_has_encoding!(OperationMetadataHash, OPERATION_METADATA_HASH); -hash_has_encoding!( - OperationMetadataListListHash, - OPERATION_METADATA_LIST_LIST_HASH -); -hash_has_encoding!(ContextHash, CONTEXT_HASH); -hash_has_encoding!(ProtocolHash, PROTOCOL_HASH); -hash_has_encoding!(ContractKt1Hash, CONTRACT_KT1HASH); -hash_has_encoding!(ContractTz1Hash, CONTRACT_TZ1HASH); -hash_has_encoding!(ContractTz2Hash, CONTRACT_TZ2HASH); -hash_has_encoding!(ContractTz3Hash, CONTRACT_TZ3HASH); -hash_has_encoding!(ContractTz4Hash, CONTRACT_TZ4HASH); -hash_has_encoding!(CryptoboxPublicKeyHash, CRYPTOBOX_PUBLIC_KEY_HASH); -hash_has_encoding!(PublicKeyEd25519, PUBLIC_KEY_ED25519); -hash_has_encoding!(PublicKeySecp256k1, PUBLIC_KEY_SECP256K1); -hash_has_encoding!(PublicKeyP256, PUBLIC_KEY_P256); -hash_has_encoding!(PublicKeyBls, PUBLIC_KEY_BLS); -hash_has_encoding!(SecretKeyEd25519, SECRET_KEY_ED25519); -hash_has_encoding!(SecretKeyBls, SECRET_KEY_BLS); -hash_has_encoding!(UnknownSignature, UNKNOWN_SIGNATURE); -hash_has_encoding!(Ed25519Signature, ED25519_SIGNATURE_HASH); -hash_has_encoding!(Secp256k1Signature, SECP256K1_SIGNATURE_HASH); -hash_has_encoding!(P256Signature, P256_SIGNATURE_HASH); -hash_has_encoding!(BlsSignature, BLS_SIGNATURE_HASH); -hash_has_encoding!(NonceHash, NONCE_HASH); -hash_has_encoding!(SmartRollupHash, SMART_ROLLUP_HASH); - -impl HasEncoding for crypto::signature::Signature { - fn encoding() -> Encoding { - Encoding::Custom - } -} - /// Creates impl HasEncoding for given struct backed by lazy_static ref instance with encoding. #[macro_export] macro_rules! has_encoding { diff --git a/tezos-encoding/src/lib.rs b/tezos-encoding/src/lib.rs index 7132fb84f7..c5ff9ac3f6 100644 --- a/tezos-encoding/src/lib.rs +++ b/tezos-encoding/src/lib.rs @@ -49,8 +49,6 @@ //! # assert_eq!(outer, result); //! ``` -extern crate tezos_crypto_rs as crypto; - mod bit_utils; pub mod types; diff --git a/tezos-encoding/src/nom.rs b/tezos-encoding/src/nom.rs index ca99b2b79b..31a3b2a8ea 100644 --- a/tezos-encoding/src/nom.rs +++ b/tezos-encoding/src/nom.rs @@ -5,7 +5,6 @@ use bitvec::slice::BitSlice; use bitvec::{bitvec, order::Msb0, view::BitView}; -use crypto::hash::HashTrait; use nom::{ branch::*, bytes::complete::*, @@ -94,7 +93,7 @@ pub mod error { } } - pub(crate) fn limit(input: NomInput<'a>, kind: BoundedEncodingKind) -> Self { + pub fn limit(input: NomInput<'a>, kind: BoundedEncodingKind) -> Self { Self { input, kind: DecodeErrorKind::Boundary(kind), @@ -220,63 +219,6 @@ pub trait NomReader<'a>: Sized { fn nom_read(input: &'a [u8]) -> NomResult<'a, Self>; } -macro_rules! hash_nom_reader { - ($hash_name:ident) => { - impl<'a> NomReader<'a> for crypto::hash::$hash_name { - #[inline(always)] - fn nom_read(input: &[u8]) -> NomResult { - map(take(Self::hash_size()), |bytes| { - Self::try_from_bytes(bytes).unwrap() - })(input) - } - } - }; -} - -hash_nom_reader!(ChainId); -hash_nom_reader!(BlockHash); -hash_nom_reader!(BlockMetadataHash); -hash_nom_reader!(BlockPayloadHash); -hash_nom_reader!(OperationHash); -hash_nom_reader!(OperationListListHash); -hash_nom_reader!(OperationMetadataHash); -hash_nom_reader!(OperationMetadataListListHash); -hash_nom_reader!(ContextHash); -hash_nom_reader!(ProtocolHash); -hash_nom_reader!(ContractKt1Hash); -hash_nom_reader!(ContractTz1Hash); -hash_nom_reader!(ContractTz2Hash); -hash_nom_reader!(ContractTz3Hash); -hash_nom_reader!(ContractTz4Hash); -hash_nom_reader!(CryptoboxPublicKeyHash); -hash_nom_reader!(PublicKeyEd25519); -hash_nom_reader!(PublicKeySecp256k1); -hash_nom_reader!(PublicKeyP256); -hash_nom_reader!(PublicKeyBls); -hash_nom_reader!(SecretKeyEd25519); -hash_nom_reader!(SecretKeyBls); -hash_nom_reader!(UnknownSignature); -hash_nom_reader!(Ed25519Signature); -hash_nom_reader!(Secp256k1Signature); -hash_nom_reader!(P256Signature); -hash_nom_reader!(BlsSignature); -hash_nom_reader!(NonceHash); -hash_nom_reader!(SmartRollupHash); - -impl<'a> NomReader<'a> for crypto::signature::Signature { - fn nom_read(input: &'a [u8]) -> NomResult<'a, Self> { - let (rest, v) = dynamic(bytes)(input)?; - if let Ok(v) = Self::try_from(v) { - Ok((rest, v)) - } else { - Err(Err::Error(DecodeError::limit( - input, - BoundedEncodingKind::Signature, - ))) - } - } -} - impl<'a> NomReader<'a> for Zarith { fn nom_read(bytes: &[u8]) -> NomResult { map(z_bignum, |big_int| big_int.into())(bytes)