Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] #2536: Introduce ffi_import for FFI clients #2557

Merged
merged 3 commits into from
Aug 8, 2022
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
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();
appetrosyan marked this conversation as resolved.
Show resolved Hide resolved
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>,
mversic marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[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