From fac854eb9d06c0888a6aaccd0a27449e21ea6169 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Mon, 18 May 2020 21:04:47 -0600 Subject: [PATCH] Remove sdk-c (#10107) --- Cargo.lock | 32 --- Cargo.toml | 1 - ci/test-checks.sh | 5 +- sdk-c/.gitignore | 14 -- sdk-c/Cargo.toml | 28 --- sdk-c/README.md | 12 - sdk-c/build.rs | 29 --- sdk-c/cbindgen.toml | 29 --- sdk-c/src/lib.rs | 602 -------------------------------------------- 9 files changed, 1 insertion(+), 751 deletions(-) delete mode 100644 sdk-c/.gitignore delete mode 100644 sdk-c/Cargo.toml delete mode 100644 sdk-c/README.md delete mode 100644 sdk-c/build.rs delete mode 100644 sdk-c/cbindgen.toml delete mode 100644 sdk-c/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7e6566e795..a8dd771fd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -407,24 +407,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "cbindgen" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "104ca409bbff8293739438c71820a2606111b5f8f81835536dc673dfd807369e" -dependencies = [ - "clap", - "heck", - "log 0.4.8", - "proc-macro2 1.0.12", - "quote 1.0.1", - "serde", - "serde_json", - "syn 1.0.19", - "tempfile", - "toml", -] - [[package]] name = "cc" version = "1.0.49" @@ -4619,20 +4601,6 @@ dependencies = [ "tiny-bip39", ] -[[package]] -name = "solana-sdk-c" -version = "1.2.0" -dependencies = [ - "bincode", - "bs58 0.3.1", - "cbindgen", - "ed25519-dalek", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "solana-sdk", -] - [[package]] name = "solana-sdk-macro" version = "1.2.0" diff --git a/Cargo.toml b/Cargo.toml index ef59ba9e26..64a801bdae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,6 @@ members = [ "ramp-tps", "runtime", "sdk", - "sdk-c", "scripts", "stake-accounts", "stake-monitor", diff --git a/ci/test-checks.sh b/ci/test-checks.sh index b591f98997..c470f4db20 100755 --- a/ci/test-checks.sh +++ b/ci/test-checks.sh @@ -24,11 +24,8 @@ fi _ cargo +"$rust_stable" fmt --all -- --check -# Clippy gets stuck for unknown reasons if sdk-c is included in the build, so check it separately. -# See https://github.com/solana-labs/solana/issues/5503 _ cargo +"$rust_stable" clippy --version -_ cargo +"$rust_stable" clippy --all --exclude solana-sdk-c -- --deny=warnings -_ cargo +"$rust_stable" clippy --manifest-path sdk-c/Cargo.toml -- --deny=warnings +_ cargo +"$rust_stable" clippy --workspace -- --deny=warnings _ cargo +"$rust_stable" audit --version _ scripts/cargo-for-all-lock-files.sh +"$rust_stable" audit --ignore RUSTSEC-2020-0002 --ignore RUSTSEC-2020-0008 diff --git a/sdk-c/.gitignore b/sdk-c/.gitignore deleted file mode 100644 index 1971718e62..0000000000 --- a/sdk-c/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -/include/ -/farf/ -/target/ - -**/*.rs.bk -.cargo - -# log files -*.log -log-*.txt - -# intellij files -/.idea/ -/solana.iml \ No newline at end of file diff --git a/sdk-c/Cargo.toml b/sdk-c/Cargo.toml deleted file mode 100644 index 21e5ca8683..0000000000 --- a/sdk-c/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "solana-sdk-c" -version = "1.2.0" -description = "Solana SDK C" -authors = ["Solana Maintainers "] -repository = "https://github.com/solana-labs/solana" -homepage = "https://solana.com/" -license = "Apache-2.0" -edition = "2018" - -[lib] -name = "solana_sdk_c" -crate-type = ["staticlib"] - -[dependencies] -bincode = "1.2.1" -bs58 = "0.3.1" -libc = "0.2.70" -rand_chacha = "0.2.2" -rand_core = { version = "0.5", default-features = false } -solana-sdk = { path = "../sdk", version = "1.2.0" } -ed25519-dalek = "1.0.0-pre.3" - -[build-dependencies] -cbindgen = "0.14.2" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/sdk-c/README.md b/sdk-c/README.md deleted file mode 100644 index e2a70da381..0000000000 --- a/sdk-c/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Solana SDK-C - -This crate exposes a C API to Solana functions written in Rust. The crate generates a static library, and uses `cbindgen` -to generate a header file during the build. To generate both: - -```shell -$ cd /sdk-c -$ SOLANA_H_OUT_DIR="$(pwd)/include" cargo build -``` - -This will generate the static library in `/target/deps` and the header file in -`/sdk-c/include`. \ No newline at end of file diff --git a/sdk-c/build.rs b/sdk-c/build.rs deleted file mode 100644 index 8376982d1e..0000000000 --- a/sdk-c/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::env; -use std::fs; -use std::path::{Path, PathBuf}; - -fn main() { - let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - - let out_path = if let Ok(path) = env::var("SOLANA_H_OUT_DIR") { - PathBuf::from(path) - } else { - let out_dir = env::var("OUT_DIR").unwrap(); - let out_dir = Path::new(&out_dir); - out_dir.join(Path::new("include")) - }; - - // Ensure `out_path` exists - fs::create_dir_all(&out_path).unwrap_or_else(|err| { - if err.kind() != std::io::ErrorKind::AlreadyExists { - panic!("Unable to create {:#?}: {:?}", out_path, err); - } - }); - - let out_path = out_path.join(Path::new("solana.h")); - let out_path = out_path.to_str().unwrap(); - - cbindgen::generate(crate_dir) - .unwrap() - .write_to_file(out_path); -} diff --git a/sdk-c/cbindgen.toml b/sdk-c/cbindgen.toml deleted file mode 100644 index 7402d47739..0000000000 --- a/sdk-c/cbindgen.toml +++ /dev/null @@ -1,29 +0,0 @@ -language = "C" -header = '''// Copyright 2019 Solana Labs, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// -// Warning, this file is autogenerated by cbindgen. Don't modify this manually. -''' -include_version = true -include_guard = "SOLANA_H" -tab_width = 4 -documentation_style = "c99" - -[parse] -parse_deps = true -include = ["solana-sdk"] - -[export] -item_types = ["enums", "structs", "unions", "typedefs", "opaque", "functions"] diff --git a/sdk-c/src/lib.rs b/sdk-c/src/lib.rs deleted file mode 100644 index f87a679b59..0000000000 --- a/sdk-c/src/lib.rs +++ /dev/null @@ -1,602 +0,0 @@ -use bincode::{deserialize, serialize}; -use ed25519_dalek::{SignatureError, KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH}; -use libc::{c_int, size_t}; -use rand_chacha::ChaChaRng; -use rand_core::SeedableRng; -use solana_sdk::{ - hash::Hash, - instruction::CompiledInstruction as CompiledInstructionNative, - message::{Message as MessageNative, MessageHeader as MessageHeaderNative}, - pubkey::Pubkey, - signature::{Keypair as KeypairNative, Signature as SignatureNative, Signer}, - transaction::Transaction as TransactionNative, -}; -use std::{ - convert::TryInto, - ffi::CString, - os::raw::c_char, - vec::Vec, - {fmt, mem, ptr, slice}, -}; - -#[repr(C)] -#[derive(Debug)] -pub struct Transaction { - /// A set of digital signatures of `account_keys`, `program_ids`, `recent_blockhash`, and `instructions`, signed by the first - /// signatures_len keys of account_keys - pub signatures: CVec, - - /// The message to sign. - pub message: Message, -} - -impl Transaction { - pub fn from_native(mut t: TransactionNative) -> Self { - t.signatures.shrink_to_fit(); - Self { - signatures: CVec::from_native( - t.signatures - .into_iter() - .map(Signature::from_native) - .collect(), - ), - message: Message::from_native(t.message), - } - } - - /// # Safety - pub unsafe fn into_native(self) -> TransactionNative { - TransactionNative { - signatures: CVec::into_native(self.signatures) - .iter() - .map(|s| s.new_native()) - .collect(), - message: self.message.into_native(), - } - } - - /// # Safety - #[allow(clippy::should_implement_trait)] - pub unsafe fn clone(&self) -> Self { - Self { - signatures: self.signatures.clone(), - message: self.message.clone(), - } - } -} - -#[repr(C)] -#[derive(Debug)] -pub struct Message { - /// The message header, identifying signed and read-only `account_keys` - pub header: MessageHeader, - - /// All the account keys used by this transaction - pub account_keys: CVec, - - /// The id of a recent ledger entry. - pub recent_blockhash: Hash, - - /// Programs that will be executed in sequence and committed in one atomic transaction if all - /// succeed. - pub instructions: CVec, -} - -impl Message { - pub fn from_native(m: MessageNative) -> Self { - Self { - header: MessageHeader::from_native(m.header), - account_keys: CVec::from_native(m.account_keys), - recent_blockhash: m.recent_blockhash, - instructions: CVec::from_native( - m.instructions - .into_iter() - .map(CompiledInstruction::from_native) - .collect(), - ), - } - } - #[allow(clippy::missing_safety_doc)] - pub unsafe fn into_native(self) -> MessageNative { - MessageNative { - header: self.header.into_native(), - account_keys: CVec::into_native(self.account_keys), - recent_blockhash: self.recent_blockhash, - instructions: CVec::into_native(self.instructions) - .into_iter() - .map(|i| i.into_native()) - .collect(), - } - } - - #[allow(clippy::should_implement_trait, clippy::missing_safety_doc)] - pub unsafe fn clone(&self) -> Self { - Self { - header: self.header.clone(), - account_keys: self.account_keys.clone(), - recent_blockhash: self.recent_blockhash, - instructions: self.instructions.clone(), - } - } -} - -/// An instruction to execute a program -#[repr(C)] -#[derive(Debug)] -pub struct CompiledInstruction { - /// Index into the transaction keys array indicating the program account that executes this instruction - pub program_id_index: u8, - - /// Ordered indices into the transaction keys array indicating which accounts to pass to the program - pub accounts: CVec, - - /// The program input data - pub data: CVec, -} - -impl CompiledInstruction { - pub fn from_native(c: CompiledInstructionNative) -> Self { - Self { - program_id_index: c.program_id_index, - accounts: CVec::from_native(c.accounts), - data: CVec::from_native(c.data), - } - } - - #[allow(clippy::missing_safety_doc)] - pub unsafe fn into_native(self) -> CompiledInstructionNative { - CompiledInstructionNative { - program_id_index: self.program_id_index, - accounts: CVec::into_native(self.accounts), - data: CVec::into_native(self.data), - } - } - - #[allow(clippy::should_implement_trait, clippy::missing_safety_doc)] - pub unsafe fn clone(&self) -> Self { - Self { - program_id_index: self.program_id_index, - accounts: self.accounts.clone(), - data: self.data.clone(), - } - } -} - -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct MessageHeader { - /// The number of signatures required for this message to be considered valid. The - /// signatures must match the first `num_required_signatures` of `account_keys`. - pub num_required_signatures: u8, - - /// The last num_readonly_signed_accounts of the signed keys are read-only accounts. Programs - /// may process multiple transactions that load read-only accounts within a single PoH entry, - /// but are not permitted to credit or debit lamports or modify account data. Transactions - /// targeting the same read-write account are evaluated sequentially. - pub num_readonly_signed_accounts: u8, - - /// The last num_readonly_unsigned_accounts of the unsigned keys are read-only accounts. - pub num_readonly_unsigned_accounts: u8, -} - -impl MessageHeader { - pub fn from_native(h: MessageHeaderNative) -> Self { - Self { - num_required_signatures: h.num_required_signatures, - num_readonly_signed_accounts: h.num_readonly_signed_accounts, - num_readonly_unsigned_accounts: h.num_readonly_unsigned_accounts, - } - } - - pub fn into_native(self) -> MessageHeaderNative { - MessageHeaderNative { - num_required_signatures: self.num_required_signatures, - num_readonly_signed_accounts: self.num_readonly_signed_accounts, - num_readonly_unsigned_accounts: self.num_readonly_unsigned_accounts, - } - } -} - -#[repr(transparent)] -#[derive(Clone, Copy)] -pub struct Signature([u8; 64]); - -impl fmt::Debug for Signature { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", bs58::encode(&self.0[..]).into_string()) - } -} - -impl fmt::Display for Signature { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", bs58::encode(&self.0[..]).into_string()) - } -} - -impl Signature { - pub fn from_native(s: SignatureNative) -> Self { - Self(s.into()) - } - - pub fn new_native(&self) -> SignatureNative { - SignatureNative::new(&self.0[..]) - } -} - -#[repr(transparent)] -#[derive(Clone)] -pub struct Keypair([u8; KEYPAIR_LENGTH]); - -impl Keypair { - pub fn from_native(k: &KeypairNative) -> Self { - Self(k.to_bytes()) - } - - pub fn new_native(&self) -> Result { - KeypairNative::from_bytes(&self.0[..]) - } -} - -/// A representation of a Rust Vec that can be passed to C. Should not be modified or copied by C code. -#[repr(C)] -#[derive(Debug)] -pub struct CVec { - data: *mut T, - len: size_t, - capacity: size_t, -} - -impl CVec { - pub fn from_native(mut v: Vec) -> Self { - let out = Self { - data: v.as_mut_ptr(), - len: v.len(), - capacity: v.capacity(), - }; - mem::forget(v); - out - } - - #[allow(clippy::missing_safety_doc)] - pub unsafe fn into_native(self) -> Vec { - Vec::from_raw_parts(self.data, self.len, self.capacity) - } -} - -impl CVec { - #[allow(clippy::should_implement_trait, clippy::missing_safety_doc)] - pub unsafe fn clone(&self) -> Self { - let native = Vec::from_raw_parts(self.data, self.len, self.capacity); - let mut new: Vec = Vec::with_capacity(native.capacity()); - as Clone>::clone_from(&mut new, &native); - mem::forget(native); - Self::from_native(new) - } -} - -impl CVec { - #[allow(clippy::should_implement_trait, clippy::missing_safety_doc)] - pub unsafe fn clone(&self) -> Self { - let native = Vec::from_raw_parts(self.data, self.len, self.capacity); - let mut new: Vec = Vec::with_capacity(native.capacity()); - for elem in &native { - new.push(elem.clone()); - } - mem::forget(native); - Self::from_native(new) - } -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_transaction(tx: *mut Transaction) { - Box::from_raw(tx); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_message(m: *mut Message) { - Box::from_raw(m); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_message_header(mh: *mut MessageHeader) { - Box::from_raw(mh); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_signature(s: *mut Signature) { - Box::from_raw(s); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_compiled_instruction(i: *mut CompiledInstruction) { - Box::from_raw(i); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_c_string(s: *mut c_char) { - CString::from_raw(s); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn new_unsigned_transaction(message: *mut Message) -> *mut Transaction { - let message = Box::from_raw(message); - let tx = Box::new(Transaction::from_native(TransactionNative::new_unsigned( - message.into_native(), - ))); - Box::into_raw(tx) -} - -/// Generate a `Keypair` from a uint8_t[32] seed. Assumes the pointer is to an array of length 32. -/// -/// # Undefined Behavior -/// -/// Causes UB if `seed` is not a pointer to an array of length 32 or if `seed` is `NULL` -/// -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn generate_keypair(seed: *const u8) -> *mut Keypair { - let seed = <&[u8] as TryInto<&[u8; PUBLIC_KEY_LENGTH]>>::try_into(slice::from_raw_parts( - seed, - PUBLIC_KEY_LENGTH, - )) - .unwrap(); // Guaranteed not to panic - let mut rng = ChaChaRng::from_seed(*seed); - let keypair = KeypairNative::generate(&mut rng); - let keypair = Box::new(Keypair::from_native(&keypair)); - Box::into_raw(keypair) -} - -/// Get a pubkey from a keypair. Returns `NULL` if the conversion causes an error -/// -/// # Undefined Behavior -/// -/// Causes UB if `keypair` is `NULL` or if `keypair` in not a pointer to a valid `Keypair` -/// -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn get_keypair_pubkey(keypair: *const Keypair) -> *mut Pubkey { - let keypair = if let Ok(k) = (*keypair).new_native() { - k - } else { - return ptr::null_mut(); - }; - let pubkey = Box::new(keypair.pubkey()); - Box::into_raw(pubkey) -} - -/// Serialize a `Transaction` and save a pointer to the resulting byte array to `serialized`, and its -/// length to `len`. Returns `0` for success, other for failure. Consumes and frees the `Transaction`. -/// -/// # Undefined Behavior -/// -/// Causes UB if any of the input pointers is `NULL`, or if `tx` is not a valid `Transaction` -/// -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn serialize_transaction( - tx: *mut Transaction, - serialized: *mut *const u8, - len: *mut size_t, -) -> c_int { - let tx = Box::from_raw(tx); - let tx = tx.into_native(); - let mut serialized_tx = if let Ok(s) = serialize(&tx) { - s - } else { - return 1; - }; - serialized_tx.shrink_to_fit(); - *serialized = serialized_tx.as_mut_ptr(); - *len = serialized_tx.len(); - mem::forget(serialized_tx); - 0 -} - -/// Deserialize an array of bytes into a `Transaction`. Returns `NULL` if deserialization fails -/// -/// # Undefined Behavior -/// -/// Causes UB if `bytes` is `NULL`, or if `bytes` does not point to a valid array of length `len` -/// -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn deserialize_transaction( - bytes: *const u8, - len: size_t, -) -> *mut Transaction { - let slice = slice::from_raw_parts(bytes, len); - let tx = if let Ok(t) = deserialize::(slice) { - t - } else { - return ptr::null_mut(); - }; - let tx = Box::new(Transaction::from_native(tx)); - Box::into_raw(tx) -} - -/// Sign a transaction with a subset of the required `Keypair`s. If the `recent_blockhash` supplied -/// does not match that of the `Transaction`, the supplied one will be used, and any existing -/// signatures will be discarded. Returns `0` for success, other for failure. -/// -/// # Undefined Behavior -/// -/// Causes UB if any of the pointers is `NULL`, or if `keypairs` does not point to a valid array of -/// `Signers` of length `num_keypairs` -/// -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn transaction_partial_sign( - tx: *mut Transaction, - keypairs: *const Keypair, - num_keypairs: size_t, - recent_blockhash: *const Hash, -) -> c_int { - let mut tx = Box::from_raw(tx); - let mut tx_native = tx.clone().into_native(); - - let keypairs = slice::from_raw_parts(keypairs, num_keypairs); - let keypairs: Vec> = keypairs.iter().map(|k| k.new_native()).collect(); - let keypairs: Vec = if keypairs.iter().all(|k| k.is_ok()) { - keypairs - .into_iter() - .map(|k| k.expect("This shouldn't ever happen")) - .collect() - } else { - return 1; - }; - let keypairs_ref: Vec<&KeypairNative> = keypairs.iter().collect(); - - let pubkeys: Vec<_> = keypairs_ref - .iter() - .map(|keypair| keypair.pubkey()) - .collect(); - let positions = if let Ok(v) = tx_native.get_signing_keypair_positions(&pubkeys) { - v - } else { - return 2; - }; - let positions: Vec = if positions.iter().all(|pos| pos.is_some()) { - positions - .iter() - .map(|pos| pos.expect("This shouldn't ever happen")) - .collect() - } else { - return 3; - }; - - tx_native.partial_sign_unchecked(&keypairs_ref, positions, *recent_blockhash); - *tx = Transaction::from_native(tx_native); - Box::into_raw(tx); - 0 -} - -/// Get the printable c-string of a Pubkey. The returned c-string must be freed with `free_c_string()` -/// Returns `NULL` if the conversion fails. -/// -/// # Undefined Behavior -/// -/// Causes UB if `pubkey` is `NULL`, or if the returned c-string is freed by any method other than -/// calling `free_c_string()` -/// -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn get_pubkey_string(pubkey: *const Pubkey) -> *mut c_char { - if let Ok(s) = CString::new(format!("{}", *pubkey)) { - s.into_raw() - } else { - ptr::null_mut() - } -} - -#[cfg(test)] -mod tests { - use crate::*; - use bincode::serialize; - use rand_chacha::ChaChaRng; - use rand_core::SeedableRng; - use solana_sdk::signature::{Keypair as KeypairNative, Signer}; - use solana_sdk::system_transaction; - - #[test] - fn test_generate_keypair() { - let seed = [1u8; 32]; - let mut rng = ChaChaRng::from_seed(seed); - let keypair = KeypairNative::generate(&mut rng); - let c_keypair = unsafe { Box::from_raw(generate_keypair(seed.as_ptr())) }; - assert_eq!(c_keypair.new_native().unwrap().pubkey(), keypair.pubkey()); - } - - #[test] - fn test_get_pubkey() { - let seed = [1u8; 32]; - unsafe { - let keypair = generate_keypair(seed.as_ptr()); - let pubkey = Box::from_raw(get_keypair_pubkey(keypair)); - let keypair = Box::from_raw(keypair); - let keypair = keypair.new_native().unwrap(); - assert_eq!(keypair.pubkey(), *pubkey); - }; - } - - #[test] - fn test_serialize_transaction() { - let key = KeypairNative::new(); - let to = Pubkey::new_rand(); - let blockhash = Hash::default(); - let tx = system_transaction::transfer(&key, &to, 50, blockhash); - let serialized = serialize(&tx).unwrap(); - let tx = Box::new(Transaction::from_native(tx)); - let tx = Box::into_raw(tx); - let mut res: *const u8 = ptr::null_mut(); - let mut len: size_t = 0; - let slice; - unsafe { - assert_eq!(0, serialize_transaction(tx, &mut res, &mut len)); - slice = slice::from_raw_parts(res, len); - } - assert_eq!(serialized, slice); - } - - #[test] - fn test_deserialize_transaction() { - let key = KeypairNative::new(); - let to = Pubkey::new_rand(); - let blockhash = Hash::default(); - let tx = system_transaction::transfer(&key, &to, 50, blockhash); - let serialized = serialize(&tx).unwrap(); - let deserialized; - unsafe { - let ret = deserialize_transaction(serialized.as_ptr(), serialized.len()); - assert_ne!(ret, ptr::null_mut()); - let ret = Box::from_raw(ret); - deserialized = ret.into_native(); - } - assert_eq!(deserialized, tx); - } - - #[test] - fn test_deserialize_transaction_bad() { - let serialized_bad = vec![0u8; 3]; - let deserialized; - unsafe { - deserialized = deserialize_transaction(serialized_bad.as_ptr(), serialized_bad.len()); - } - assert_eq!(deserialized, ptr::null_mut()); - } - - #[test] - fn test_get_pubkey_string() { - let pubkey = Pubkey::new_rand(); - let str_native = format!("{}", pubkey); - let str_c; - unsafe { - str_c = CString::from_raw(get_pubkey_string(&pubkey)); - } - let str_c = str_c.into_string().unwrap(); - assert_eq!(str_native, str_c); - } - - #[test] - fn test_transaction_partial_sign() { - let key_native = KeypairNative::new(); - let to = Pubkey::new_rand(); - let blockhash = Hash::default(); - let mut tx_native = system_transaction::transfer(&key_native, &to, 50, blockhash); - let tx = Box::into_raw(Box::new(Transaction::from_native(tx_native.clone()))); - let key = Keypair::from_native(&key_native); - let tx2; - unsafe { - assert_eq!(0, transaction_partial_sign(tx, &key, 1, &blockhash)); - tx2 = Box::from_raw(tx).into_native(); - } - tx_native.partial_sign(&[&key_native], blockhash); - assert_eq!(tx_native, tx2); - } -}