Skip to content

Commit

Permalink
[feature] hyperledger-iroha#2536: Introduce ffi_import for FFI clie…
Browse files Browse the repository at this point in the history
…nts (hyperledger-iroha#2557)

Signed-off-by: Marin Veršić <marin.versic101@gmail.com>
  • Loading branch information
mversic committed Sep 9, 2022
1 parent ee6d4e3 commit 046f4b5
Show file tree
Hide file tree
Showing 39 changed files with 2,363 additions and 1,644 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ default = ["std"]
std = ["ursa"]
# Force static linking
vendored = ["openssl-sys"]
# Generate extern functions callable via FFI
ffi = ["iroha_ffi"]
# Replace structures and methods with FFI equivalents to facilitate dynamic linkage (mainly used in smartcontracts)
ffi_import = []

# Expose FFI API for dynamic linking (Internal use only)
ffi_export = ["std"]

[dependencies]
iroha_primitives = { path = "../primitives", version = "=2.0.0-pre-rc.7", default-features = false }
iroha_ffi = { path = "../ffi", version = "=2.0.0-pre-rc.7", optional = true }
iroha_ffi = { path = "../ffi", version = "=2.0.0-pre-rc.7" }
iroha_schema = { path = "../schema" }

derive_more = { version = "0.99.16", default-features = false, features = ["deref", "deref_mut", "display"] }
Expand Down
14 changes: 14 additions & 0 deletions crypto/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Build script
//!
//! Warn if `ffi_import` and `ffi_export` features are active at the same time

fn main() {
let ffi_import = std::env::var_os("CARGO_FEATURE_FFI_IMPORT").is_some();
let ffi_export = std::env::var_os("CARGO_FEATURE_FFI_EXPORT").is_some();

#[allow(clippy::print_stderr)]
if ffi_import && ffi_export {
eprintln!("cargo:warning=Features `ffi_export` and `ffi_import` are mutually exclusive");
eprintln!("cargo:warning=When both active, `ffi_import` feature takes precedence");
}
}
162 changes: 98 additions & 64 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ mod signature;
mod varint;

#[cfg(not(feature = "std"))]
use alloc::{format, string::String, vec::Vec};
use alloc::{alloc::alloc, boxed::Box, format, string::String, vec::Vec};
use core::{fmt, str::FromStr};
#[cfg(feature = "std")]
use std::alloc::alloc;

#[cfg(feature = "base64")]
pub use base64;
use derive_more::{DebugCustom, Display};
use getset::Getters;
pub use hash::*;
#[cfg(feature = "ffi")]
use iroha_ffi::{ffi_export, IntoFfi, TryFromFfi};
use iroha_ffi::{IntoFfi, TryFromReprC};
use iroha_primitives::conststr::ConstString;
use iroha_schema::IntoSchema;
pub use merkle::MerkleTree;
Expand Down Expand Up @@ -63,23 +64,24 @@ pub struct NoSuchAlgorithm;
#[cfg(feature = "std")]
impl std::error::Error for NoSuchAlgorithm {}

/// Algorithm for hashing
#[cfg_attr(feature = "ffi", derive(IntoFfi, TryFromFfi))]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Algorithm {
/// Ed25519
#[display(fmt = "{}", "ED_25519")]
Ed25519,
/// Secp256k1
#[display(fmt = "{}", "SECP_256_K1")]
Secp256k1,
/// BlsNormal
#[display(fmt = "{}", "BLS_NORMAL")]
BlsNormal,
/// BlsSmall
#[display(fmt = "{}", "BLS_SMALL")]
BlsSmall,
ffi::ffi_item! {
/// Algorithm for hashing
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, IntoFfi, TryFromReprC)]
#[repr(u8)]
pub enum Algorithm {
/// Ed25519
#[display(fmt = "{}", "ED_25519")]
Ed25519,
/// Secp256k1
#[display(fmt = "{}", "SECP_256_K1")]
Secp256k1,
/// BlsNormal
#[display(fmt = "{}", "BLS_NORMAL")]
BlsNormal,
/// BlsSmall
#[display(fmt = "{}", "BLS_SMALL")]
BlsSmall,
}
}

impl Default for Algorithm {
Expand Down Expand Up @@ -164,15 +166,16 @@ impl KeyGenConfiguration {
}
}

/// Pair of Public and Private keys.
#[cfg_attr(feature = "ffi", derive(IntoFfi, TryFromFfi))]
#[derive(Debug, Clone, PartialEq, Eq, Getters, Serialize)]
#[getset(get = "pub")]
pub struct KeyPair {
/// Public Key.
public_key: PublicKey,
/// Private Key.
private_key: PrivateKey,
ffi::ffi_item! {
/// Pair of Public and Private keys.
#[derive(Debug, Clone, PartialEq, Eq, Getters, Serialize, IntoFfi, TryFromReprC)]
#[getset(get = "pub")]
pub struct KeyPair {
/// Public Key.
public_key: PublicKey,
/// Private Key.
private_key: PrivateKey,
}
}

/// Error when dealing with cryptographic functions
Expand Down Expand Up @@ -363,21 +366,26 @@ impl From<multihash::ConvertError> for KeyParseError {
#[cfg(feature = "std")]
impl std::error::Error for KeyParseError {}

/// Public Key used in signatures.
#[derive(DebugCustom, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, IntoSchema)]
#[cfg_attr(feature = "ffi", derive(IntoFfi, TryFromFfi))]
#[debug(
fmt = "{{ digest: {digest_function}, payload: {} }}",
"hex::encode_upper(payload.as_slice())"
)]
pub struct PublicKey {
/// Digest function
digest_function: ConstString,
/// payload of key
payload: Vec<u8>,
ffi::ffi_item! {
/// Public Key used in signatures.
#[derive(DebugCustom, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, IntoFfi, TryFromReprC, IntoSchema)]
#[debug(
fmt = "{{ digest: {digest_function}, payload: {} }}",
"hex::encode_upper(payload.as_slice())"
)]
pub struct PublicKey {
/// Digest function
digest_function: ConstString,
/// Key payload
payload: Vec<u8>,
}
}

#[cfg_attr(feature = "ffi", ffi_export)]
#[cfg_attr(
all(feature = "ffi_export", not(feature = "ffi_import")),
iroha_ffi::ffi_export
)]
#[cfg_attr(feature = "ffi_import", iroha_ffi::ffi_import)]
impl PublicKey {
/// Key payload
pub fn payload(&self) -> &[u8] {
Expand Down Expand Up @@ -494,21 +502,26 @@ impl Decode for PublicKey {
}
}

/// Private Key used in signatures.
#[derive(DebugCustom, Display, Clone, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "ffi", derive(IntoFfi, TryFromFfi))]
#[debug(fmt = "{{ digest: {digest_function}, payload: {:X?}}}", payload)]
#[display(fmt = "{}", "hex::encode(payload)")]
#[allow(clippy::multiple_inherent_impl)]
pub struct PrivateKey {
/// Digest function
digest_function: ConstString,
/// key payload. WARNING! Do not use `"string".as_bytes()` to obtain the key.
#[serde(with = "hex::serde")]
payload: Vec<u8>,
ffi::ffi_item! {
/// Private Key used in signatures.
#[derive(DebugCustom, Clone, PartialEq, Eq, Display, Serialize, IntoFfi, TryFromReprC)]
#[debug(fmt = "{{ digest: {digest_function}, payload: {:X?}}}", payload)]
#[display(fmt = "{}", "hex::encode(payload)")]
#[allow(clippy::multiple_inherent_impl)]
pub struct PrivateKey {
/// Digest function
digest_function: ConstString,
/// Key payload. WARNING! Do not use `"string".as_bytes()` to obtain the key.
#[serde(with = "hex::serde")]
payload: Vec<u8>,
}
}

#[cfg_attr(feature = "ffi", ffi_export)]
#[cfg_attr(
all(feature = "ffi_export", not(feature = "ffi_import")),
iroha_ffi::ffi_export
)]
#[cfg_attr(feature = "ffi_import", iroha_ffi::ffi_import)]
impl PrivateKey {
/// Key payload
pub fn payload(&self) -> &[u8] {
Expand Down Expand Up @@ -574,18 +587,39 @@ impl<'de> Deserialize<'de> for PrivateKey {
}
}

#[cfg(feature = "ffi")]
mod ffi {
use iroha_ffi::{gen_ffi_impl, handles};
pub mod ffi {
//! Definitions and implementations of FFI related functionalities

use super::*;

macro_rules! ffi_item {
($it: item) => {
#[cfg(not(feature = "ffi_import"))]
$it

#[cfg(feature = "ffi_import")]
iroha_ffi::ffi! { $it }
};
}

#[cfg(any(feature = "ffi_export", feature = "ffi_import"))]
macro_rules! ffi_fn {
($macro_name: ident) => {
iroha_ffi::$macro_name! { Clone: KeyPair, PublicKey, PrivateKey }
iroha_ffi::$macro_name! { Eq: KeyPair, PublicKey, PrivateKey }
iroha_ffi::$macro_name! { Ord: PublicKey }
iroha_ffi::$macro_name! { Drop: KeyPair, PublicKey, PrivateKey }
};
}

use super::{KeyPair, PrivateKey, PublicKey};
iroha_ffi::handles! {KeyPair, PublicKey, PrivateKey}

handles! {0, KeyPair, PublicKey, PrivateKey}
#[cfg(feature = "ffi_import")]
ffi_fn! {decl_ffi_fn}
#[cfg(all(feature = "ffi_export", not(feature = "ffi_import")))]
ffi_fn! {def_ffi_fn}

gen_ffi_impl! { Clone: KeyPair, PublicKey, PrivateKey}
gen_ffi_impl! { Eq: KeyPair, PublicKey, PrivateKey}
gen_ffi_impl! { Ord: PublicKey }
gen_ffi_impl! { Drop: KeyPair, PublicKey, PrivateKey}
pub(crate) use ffi_item;
}

/// The prelude re-exports most commonly used traits, structs and macros from this crate.
Expand Down
8 changes: 5 additions & 3 deletions data_model/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ default = ["std"]
# Disabled for WASM interoperability, to reduce the binary size.
# Please refer to https://docs.rust-embedded.org/book/intro/no-std.html
std = ["iroha_macro/std", "iroha_version/std", "iroha_version/warp", "iroha_crypto/std", "iroha_primitives/std", "thiserror", "strum/std", "dashmap", "tokio"]
# Generate extern functions callable via FFI
ffi = ["iroha_crypto/ffi", "iroha_ffi"]
# Replace structures and methods with FFI equivalents to facilitate dynamic linkage (mainly used in smartcontracts)
ffi_import = ["iroha_crypto/ffi_import"]

# Expose FFI API for dynamic linking (Internal use only)
ffi_export = ["std", "iroha_crypto/ffi_export"]
# Expose API for mutating structures (Internal use only)
mutable_api = []

Expand All @@ -35,7 +37,7 @@ iroha_crypto = { path = "../crypto", version = "=2.0.0-pre-rc.7", default-featur
iroha_macro = { path = "../macro", version = "=2.0.0-pre-rc.7", default-features = false }
iroha_version = { path = "../version", version = "=2.0.0-pre-rc.7", default-features = false, features = ["derive", "json", "scale"] }
iroha_schema = { path = "../schema", version = "=2.0.0-pre-rc.7" }
iroha_ffi = { path = "../ffi", version = "=2.0.0-pre-rc.7", optional = true }
iroha_ffi = { path = "../ffi", version = "=2.0.0-pre-rc.7" }

dashmap = { version = "4.0", optional = true}
tokio = { version = "1.6.0", features = ["sync", "rt-multi-thread"], optional = true}
Expand Down
14 changes: 14 additions & 0 deletions data_model/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Build script
//!
//! Warn if `ffi_import` and `ffi_export` features are active at the same time

fn main() {
let ffi_import = std::env::var_os("CARGO_FEATURE_FFI_IMPORT").is_some();
let ffi_export = std::env::var_os("CARGO_FEATURE_FFI_EXPORT").is_some();

#[allow(clippy::print_stderr)]
if ffi_import && ffi_export {
println!("cargo:warning=Features `ffi_export` and `ffi_import` are mutually exclusive");
println!("cargo:warning=When both active, `ffi_import` feature takes precedence");
}
}
Loading

0 comments on commit 046f4b5

Please sign in to comment.