From a3231d82e69133c6887b03edfbf88e459ea87084 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Fri, 10 Nov 2017 09:11:09 -0700 Subject: [PATCH 01/18] Updated default wallet to SQLCipher Signed-off-by: Michael Lodder --- libindy/Cargo.toml | 2 +- libindy/src/services/wallet/default.rs | 341 +++++++++++++++++++++++-- 2 files changed, 323 insertions(+), 20 deletions(-) diff --git a/libindy/Cargo.toml b/libindy/Cargo.toml index 5617824b4f..d22edfbbb1 100644 --- a/libindy/Cargo.toml +++ b/libindy/Cargo.toml @@ -44,7 +44,7 @@ libc = "0.2.21" log = "0.3.7" openssl = { version = "0.9.11", optional = true } rand = "0.3" -rusqlite = "0.10.1" +rusqlcipher = { version = "0.14.2", features=["bundled"] } rust-base58 = {version = "0.0.4", optional = true} base64 = "0.6.0" serde = "1.0" diff --git a/libindy/src/services/wallet/default.rs b/libindy/src/services/wallet/default.rs index a39a4dd6b4..f89734f303 100644 --- a/libindy/src/services/wallet/default.rs +++ b/libindy/src/services/wallet/default.rs @@ -1,4 +1,4 @@ -extern crate rusqlite; +extern crate rusqlcipher; extern crate time; use super::{Wallet, WalletType}; @@ -8,7 +8,7 @@ use errors::wallet::WalletError; use utils::environment::EnvironmentUtils; use utils::json::JsonDecodable; -use self::rusqlite::Connection; +use self::rusqlcipher::Connection; use self::time::Timespec; use std::error::Error; @@ -29,11 +29,20 @@ impl Default for DefaultWalletRuntimeConfig { } } -#[derive(Deserialize)] -struct DefaultWalletCredentials {} +#[derive(Deserialize, Debug)] +struct DefaultWalletCredentials { + key: String, + rekey: Option +} impl<'a> JsonDecodable<'a> for DefaultWalletCredentials {} +impl Default for DefaultWalletCredentials { + fn default() -> Self { + DefaultWalletCredentials { key: String::new(), rekey: None } + } +} + struct DefaultWalletRecord { key: String, value: String, @@ -43,7 +52,8 @@ struct DefaultWalletRecord { struct DefaultWallet { name: String, pool_name: String, - config: DefaultWalletRuntimeConfig + config: DefaultWalletRuntimeConfig, + credentials: DefaultWalletCredentials } impl DefaultWallet { @@ -54,14 +64,15 @@ impl DefaultWallet { DefaultWallet { name: name.to_string(), pool_name: pool_name.to_string(), - config: config + config: config, + credentials: credentials } } } impl Wallet for DefaultWallet { fn set(&self, key: &str, value: &str) -> Result<(), WalletError> { - _open_connection(self.name.as_str())? + _open_connection(self.name.as_str(), &self.credentials)? .execute( "INSERT OR REPLACE INTO wallet (key, value, time_created) VALUES (?1, ?2, ?3)", &[&key.to_string(), &value.to_string(), &time::get_time()])?; @@ -69,7 +80,7 @@ impl Wallet for DefaultWallet { } fn get(&self, key: &str) -> Result { - let record = _open_connection(self.name.as_str())? + let record = _open_connection(self.name.as_str(), &self.credentials)? .query_row( "SELECT key, value, time_created FROM wallet WHERE key = ?1 LIMIT 1", &[&key.to_string()], |row| { @@ -83,7 +94,7 @@ impl Wallet for DefaultWallet { } fn list(&self, key_prefix: &str) -> Result, WalletError> { - let connection = _open_connection(self.name.as_str())?; + let connection = _open_connection(self.name.as_str(), &self.credentials)?; let mut stmt = connection.prepare("SELECT key, value, time_created FROM wallet WHERE key like ?1 order by key")?; let records = stmt.query_map(&[&format!("{}%", key_prefix)], |row| { DefaultWalletRecord { @@ -104,7 +115,7 @@ impl Wallet for DefaultWallet { } fn get_not_expired(&self, key: &str) -> Result { - let record = _open_connection(self.name.as_str())? + let record = _open_connection(self.name.as_str(), &self.credentials)? .query_row( "SELECT key, value, time_created FROM wallet WHERE key = ?1 LIMIT 1", &[&key.to_string()], |row| { @@ -151,7 +162,12 @@ impl WalletType for DefaultWalletType { return Err(WalletError::AlreadyExists(name.to_string())) } - _open_connection(name).map_err(map_err_trace!())? + let runtime_auth = match credentials { + Some(auth) => DefaultWalletCredentials::from_json(auth)?, + None => DefaultWalletCredentials::default() + }; + + _open_connection(name, &runtime_auth).map_err(map_err_trace!())? .execute("CREATE TABLE wallet (key TEXT CONSTRAINT constraint_name PRIMARY KEY, value TEXT NOT NULL, time_created TEXT NOT_NULL)", &[]) .map_err(map_err_trace!())?; trace!("DefaultWalletType.create <<"); @@ -170,13 +186,17 @@ impl WalletType for DefaultWalletType { None => DefaultWalletRuntimeConfig::default() }; - // FIXME: parse and implement credentials!!! + let runtime_auth = match credentials { + Some(auth) => DefaultWalletCredentials::from_json(auth)?, + None => DefaultWalletCredentials::default() + }; + Ok(Box::new( DefaultWallet::new( name, pool_name, runtime_config, - DefaultWalletCredentials {}))) + runtime_auth))) } } @@ -186,7 +206,7 @@ fn _db_path(name: &str) -> PathBuf { path } -fn _open_connection(name: &str) -> Result { +fn _open_connection(name: &str, credentials: &DefaultWalletCredentials) -> Result { let path = _db_path(name); if !path.parent().unwrap().exists() { fs::DirBuilder::new() @@ -194,13 +214,69 @@ fn _open_connection(name: &str) -> Result { .create(path.parent().unwrap())?; } - Ok(Connection::open(path)?) + let conn = Connection::open(path)?; + conn.execute(&format!("PRAGMA key='{}'", credentials.key), &[])?; + + match credentials.rekey { + None => Ok(conn), + Some(ref rk) => { + if credentials.key.len() == 0 && rk.len() > 0 { + _export_unencrypted_to_encrypted(conn, name, &rk) + } else if rk.len() > 0 { + conn.execute(&format!("PRAGMA rekey='{}'", rk), &[])?; + Ok(conn) + } else { + _export_encrypted_to_unencrypted(conn, name) + } + } + } +} + +fn _export_encrypted_to_unencrypted(conn: Connection, name: &str) -> Result { + let mut path = EnvironmentUtils::wallet_path(name); + path.push("plaintext.db"); + + conn.execute(&format!("ATTACH DATABASE {:?} AS plaintext KEY ''", path), &[])?; + conn.query_row(&"SELECT sqlcipher_export('plaintext')", &[], |row|{})?; + conn.execute(&"DETACH DATABASE plaintext", &[])?; + let r = conn.close(); + if let Err((c, w)) = r { + Err(WalletError::from(w)) + } else { + let wallet = _db_path(name); + fs::remove_file(&wallet)?; + fs::rename(&path, &wallet)?; + + Ok(Connection::open(wallet)?) + } } -impl From for WalletError { - fn from(err: rusqlite::Error) -> WalletError { +fn _export_unencrypted_to_encrypted(conn: Connection, name: &str, key: &str) -> Result { + let mut path = EnvironmentUtils::wallet_path(name); + path.push("encrypted.db"); + + let sql = format!("ATTACH DATABASE {:?} AS encrypted KEY '{}'", path, key); + conn.execute(&sql, &[])?; + conn.query_row(&"SELECT sqlcipher_export('encrypted')", &[], |row| {})?; + conn.execute(&"DETACH DATABASE encrypted", &[])?; + let r = conn.close(); + if let Err((c, w)) = r { + Err(WalletError::from(w)) + } else { + let wallet = _db_path(name); + fs::remove_file(&wallet)?; + fs::rename(&path, &wallet)?; + + let new = Connection::open(wallet)?; + new.execute(&format!("PRAGMA key='{}'", key), &[])?; + Ok(new) + } +} + +impl From for WalletError { + fn from(err: rusqlcipher::Error) -> WalletError { match err { - rusqlite::Error::QueryReturnedNoRows => WalletError::NotFound(format!("Wallet record is not found: {}", err.description())), + rusqlcipher::Error::QueryReturnedNoRows => WalletError::NotFound(format!("Wallet record is not found: {}", err.description())), _ => WalletError::CommonError(CommonError::InvalidState(format!("Unexpected SQLite error: {}", err.description()))) } } @@ -213,6 +289,9 @@ mod tests { use errors::wallet::WalletError; use utils::test::TestUtils; + use serde_json; + use self::serde_json::Error as JsonError; + use std::time::{Duration}; use std::thread; @@ -403,4 +482,228 @@ mod tests { TestUtils::cleanup_indy_home(); } -} \ No newline at end of file + + #[test] + fn default_wallet_credentials_deserialize() { + let empty: Result = serde_json::from_str(r#"{}"#); + assert!(empty.is_err()); + + let one: Result = serde_json::from_str(r#"{"key":""}"#); + assert!(one.is_ok()); + let rone = one.unwrap(); + assert_eq!(rone.key, ""); + assert_eq!(rone.rekey, None); + + let two: Result = serde_json::from_str(r#"{"key":"thisisatest","rekey":null}"#); + assert!(two.is_ok()); + let rtwo = two.unwrap(); + assert_eq!(rtwo.key, "thisisatest"); + assert_eq!(rtwo.rekey, None); + + let three: Result = serde_json::from_str(r#"{"key":"","rekey":"thisismynewpassword"}"#); + assert!(three.is_ok()); + let rthree = three.unwrap(); + assert_eq!(rthree.key, ""); + assert_eq!(rthree.rekey, Some("thisismynewpassword".to_string())); + + let four: Result = serde_json::from_str(r#"{"key": "", "rekey": ""}"#); + assert!(four.is_ok()); + let rfour = four.unwrap(); + assert_eq!(rfour.key, ""); + assert_eq!(rfour.rekey, Some("".to_string())); + } + + #[test] + fn default_wallet_convert_nonencrypted_to_encrypted() { + TestUtils::cleanup_indy_home(); + { + let default_wallet_type = DefaultWalletType::new(); + default_wallet_type.create("mywallet", None, Some(r#"{"key":""}"#)).unwrap(); + let wallet = default_wallet_type.open("mywallet", "pool1", None, None, Some(r#"{"key":""}"#)).unwrap(); + + wallet.set("key1::subkey1", "value1").unwrap(); + wallet.set("key1::subkey2", "value2").unwrap(); + } + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("mywallet", "pool1", None, None, Some(r#"{"key":"", "rekey":"thisisatest"}"#)).unwrap(); + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("mywallet", "pool1", None, None, Some(r#"{"key":"thisisatest"}"#)).unwrap(); + + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + + TestUtils::cleanup_indy_home(); + } + + #[test] + fn default_wallet_convert_encrypted_to_nonencrypted() { + TestUtils::cleanup_indy_home(); + { + let default_wallet_type = DefaultWalletType::new(); + default_wallet_type.create("mywallet", None, Some(r#"{"key":"thisisatest"}"#)).unwrap(); + let wallet = default_wallet_type.open("mywallet", "pool1", None, None, Some(r#"{"key":"thisisatest"}"#)).unwrap(); + + wallet.set("key1::subkey1", "value1").unwrap(); + wallet.set("key1::subkey2", "value2").unwrap(); + } + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("mywallet", "pool1", None, None, Some(r#"{"key":"thisisatest", "rekey":""}"#)).unwrap(); + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("mywallet", "pool1", None, None, Some(r#"{"key":""}"#)).unwrap(); + + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + + TestUtils::cleanup_indy_home(); + } + + #[test] + fn default_wallet_create_encrypted() { + TestUtils::cleanup_indy_home(); + + { + let default_wallet_type = DefaultWalletType::new(); + default_wallet_type.create("encrypted_wallet", None, Some(r#"{"key":"test"}"#)).unwrap(); + let wallet = default_wallet_type.open("encrypted_wallet", "pool1", None, None, Some(r#"{"key":"test"}"#)).unwrap(); + + wallet.set("key1::subkey1", "value1").unwrap(); + wallet.set("key1::subkey2", "value2").unwrap(); + + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("encrypted_wallet", "pool1", None, None, None).unwrap(); + + let wallet_error = wallet.list("key1::").err(); + match wallet_error { + Some(error) => { + assert_eq!(error.description(), String::from("Unexpected SQLite error: file is encrypted or is not a database")); + } + None => assert!(false) + }; + } + + TestUtils::cleanup_indy_home(); + } + + #[test] + fn default_wallet_change_key() { + TestUtils::cleanup_indy_home(); + + { + let default_wallet_type = DefaultWalletType::new(); + default_wallet_type.create("encrypted_wallet", None, Some(r#"{"key":"test"}"#)).unwrap(); + let wallet = default_wallet_type.open("encrypted_wallet", "pool1", None, None, Some(r#"{"key":"test"}"#)).unwrap(); + + wallet.set("key1::subkey1", "value1").unwrap(); + wallet.set("key1::subkey2", "value2").unwrap(); + + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("encrypted_wallet", "pool1", None, None, Some(r#"{"key":"test","rekey":"newtest"}"#)).unwrap(); + + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + + { + let default_wallet_type = DefaultWalletType::new(); + let wallet = default_wallet_type.open("encrypted_wallet", "pool1", None, None, Some(r#"{"key":"newtest"}"#)).unwrap(); + + let mut key_values = wallet.list("key1::").unwrap(); + key_values.sort(); + assert_eq!(2, key_values.len()); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey2", key); + assert_eq!("value2", value); + + let (key, value) = key_values.pop().unwrap(); + assert_eq!("key1::subkey1", key); + assert_eq!("value1", value); + } + + TestUtils::cleanup_indy_home(); + } +} From d6ab68a7fa57868413325559bd4463cccd5f9a37 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Fri, 10 Nov 2017 09:11:29 -0700 Subject: [PATCH 02/18] Fixed Grammar in the README Signed-off-by: Michael Lodder --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ffa72e778..ccbf016121 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ us on [Hyperledger's Rocket.Chat](https://chat.hyperledger.org/) at #indy-sdk to * [iOS](wrappers/ios/ios-build.md) ## Binaries -Builded binaries can be downloaded from https://repo.sovrin.org/: +Pre-Built binaries can be downloaded from https://repo.sovrin.org/: * lib/apt/xenial/{master,stable,rc} - Ubuntu deb packages * windows/libindy/{master,stable,rc} - Windows zip-archive with all required DLLs (include libindy itself) and headers * windows/libindy/deps/ - Windows zip archive with dependencies (DLLs and headers) to build libindy from sources From ac2e55ff3c7623aa90200281dcf1acd7b15b0de3 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Fri, 10 Nov 2017 09:11:50 -0700 Subject: [PATCH 03/18] Updated windows build instructions to be more specific Signed-off-by: Michael Lodder --- doc/windows-build.md | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/doc/windows-build.md b/doc/windows-build.md index 29a020281f..f6a4a9093a 100644 --- a/doc/windows-build.md +++ b/doc/windows-build.md @@ -1,9 +1,44 @@ # Setup Indy SDK build environment for Windows +## Build Environment + +1. Setup a windows virtual machine. Free images are available at [here](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/) +1. Launch the virtual machine +1. Download Visual Studio Community Edition 2017 +1. Check the boxes for the _Desktop development with C++_ and _Linux Development with C++_ +1. In the summary portion on the right hand side also check _C++/CLI support_ +1. Click install +1. Download git-scm for windows [here](https://git-scm.com/downloads/win) +1. Install git for windows using: + 1. _Use Git from Git Bash Only_ so it doesn't change any path settings of the command prompt + 1. _Checkout as is, commit Unix-style line endings_. You shouldn't be commiting anything anyway but just in case + 1. _Use MinTTY_ + 1. Check all the boxes for: + 1. Enable file system caching + 1. Enable Git Credential Manager + 1. Enable symbolic links +1. Download rust for windows [here](https://www.rust-lang.org/en-US/install.html) + 1. Choose installation option *1* + ## Get/build dependencies -All prebuilt can be downloaded from -https://repo.sovrin.org/windows/libindy/deps/ +- Open a the Git Bash command prompt +- Change directories to Downloads: +```bash +cd Downloads +``` + +- Clone the _indy-sdk_ repository from github. +```bash +git clone https://github.com/hyperledger/indy-sdk.git +``` + +- Download the prebuilt dependencies [here](https://repo.sovrin.org/windows/libindy/deps/) +- Extract them into the folder _C:\BIN\x64_ +> It really doesn't matter where you put these as long as you remember where so you can set +> the environment variables to this path + +- If you are not building dependencies from source you may skip to *Build* ### Binary deps @@ -44,6 +79,7 @@ Checkout https://github.com/evernym/libzmq-pw repository. - Get binary dependencies (libamcl*, openssl, libsodium, libzmq, sqlite3). - Put all *.{lib,dll} into one directory and headers into include/ subdirectory. +- Open a windows command prompt - Configure MSVS environment to privide 64-bit builds by execution of `vcvars64.bat`: ``` @@ -61,7 +97,7 @@ Checkout https://github.com/evernym/libzmq-pw repository. - set OPENSSL_DIR=C:\BIN\x64 - set PATH to find .dlls: - set PATH=C:\BIN\x64\lib;%PATH% -- change dir to indy-client and run cargo (you may want to add --release --target x86_64-pc-windows-msvc keys to cargo) +- change dir to indy-sdk/libindy and run cargo (you may want to add --release --target x86_64-pc-windows-msvc keys to cargo) ## openssl-sys workaround @@ -100,4 +136,4 @@ Then try to rebuild whole project. ``` RUST_TEST_THREADS=1 cargo test - ``` \ No newline at end of file + ``` From 7a5d5195430cc19f88f7a2da5671c3f72b933f4d Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Mon, 13 Nov 2017 09:59:26 -0700 Subject: [PATCH 04/18] Updated crate version Signed-off-by: Michael Lodder --- libindy/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libindy/Cargo.toml b/libindy/Cargo.toml index d22edfbbb1..c59a83c17f 100644 --- a/libindy/Cargo.toml +++ b/libindy/Cargo.toml @@ -44,7 +44,7 @@ libc = "0.2.21" log = "0.3.7" openssl = { version = "0.9.11", optional = true } rand = "0.3" -rusqlcipher = { version = "0.14.2", features=["bundled"] } +rusqlcipher = { version = "0.14.3", features=["bundled"] } rust-base58 = {version = "0.0.4", optional = true} base64 = "0.6.0" serde = "1.0" From c4452d1143270227cd3b42c4864f6451e70dcc2e Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Tue, 14 Nov 2017 16:31:55 +0300 Subject: [PATCH 05/18] Add simple MacOS pipeline for CI. Signed-off-by: Sergey Minaev --- Jenkinsfile.ci | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 71b9835035..e2843f4353 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -6,6 +6,7 @@ def testing() { stage('Testing') { parallel([ 'ubuntu-test' : { ubuntuTesting() }, + 'macos-test' : { macosTesting() }, 'redhat-test' : { rhelTesting() }, 'windows-test': { windowsTesting() } ]) @@ -68,6 +69,28 @@ def windowsTesting() { } } +def macosTesting() { + node('macos') { + stage('MacOS Test') { + try { + echo "MacOS Test: Checkout scm" + checkout scm + + dir('libindy') { + echo "MacOS Test: Build" + sh "cargo build" + + // TODO testing + } + + //TODO wrappers testing + } finally { + step([$class: 'WsCleanup']) + } + } + } +} + def ubuntuTesting() { node('ubuntu') { stage('Ubuntu Test') { From ca2727a3c39f448d29b787e460bf9fd6486b21e6 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Tue, 14 Nov 2017 17:57:15 +0300 Subject: [PATCH 06/18] [ios] Fix Podfile for wrapper tests: update libindy dependence to 1.1.0 Signed-off-by: Sergey Minaev --- wrappers/ios/libindy-pod/Podfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrappers/ios/libindy-pod/Podfile b/wrappers/ios/libindy-pod/Podfile index a659c18f89..bf0a3b29af 100644 --- a/wrappers/ios/libindy-pod/Podfile +++ b/wrappers/ios/libindy-pod/Podfile @@ -9,7 +9,7 @@ def appPods pod 'libzmq-pw',"4.2.2" pod 'OpenSSL' pod 'milagro', "3.0.0" - pod 'libindy', "0.1.4" + pod 'libindy', "1.1.0" end target 'Indy-demo' do From 45d49cb8ed1606f27c4a45ab561d42d9cbc1352c Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Tue, 14 Nov 2017 17:58:22 +0300 Subject: [PATCH 07/18] [ios] Add draft version of iOS pipeline. Signed-off-by: Sergey Minaev --- Jenkinsfile.ci | 61 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index e2843f4353..ef7db0b707 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -7,6 +7,7 @@ def testing() { parallel([ 'ubuntu-test' : { ubuntuTesting() }, 'macos-test' : { macosTesting() }, + 'ios-test' : { iosTesting() }, 'redhat-test' : { rhelTesting() }, 'windows-test': { windowsTesting() } ]) @@ -91,6 +92,34 @@ def macosTesting() { } } +def iosTesting() { + node('macos') { + stage('iOS Test') { + def poolInst + try { + echo "iOS Test: Checkout scm" + checkout scm + + echo "iOS Test: Running pool" + def poolEnv = dockerBuild('indy_pool', 'ci/indy-pool.dockerfile ci') + poolInst = poolEnv.run('-p 9701-9708:9701-9708') + + dir('wrappers/ios/libindy-pod') { + echo "iOS Test: Build" + + echo "iOS Test: Installing dependencies (pods)" + sh "pod install" + + echo "iOS Test: Testing" + sh "xcodebuild test -workspace Indy.xcworkspace -scheme Indy-demo -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=11.1'" + } + } finally { + closePool("iOS Test", null, poolInst) + } + } + } +} + def ubuntuTesting() { node('ubuntu') { stage('Ubuntu Test') { @@ -195,10 +224,12 @@ def openPool(env_name, network_name, pool_type = null, pool_ver = null, plenum_v def closePool(env_name, network_name, poolInst) { echo "${env_name} Test: Cleanup" - try { - sh "docker network inspect ${network_name}" - } catch (error) { - echo "${env_name} Tests: error while inspect network ${network_name} - ${error}" + if (network_name != null) { + try { + sh "docker network inspect ${network_name}" + } catch (error) { + echo "${env_name} Tests: error while inspect network ${network_name} - ${error}" + } } try { echo "${env_name} Test: stop pool" @@ -206,16 +237,18 @@ def closePool(env_name, network_name, poolInst) { } catch (error) { echo "${env_name} Tests: error while stop pool ${error}" } - try { - sh "docker ps --format '{{.ID}}' --filter network=${network_name} | xargs docker rm -f" - } catch (error) { - echo "${env_name} Test: error while force clean-up network ${network_name} - ${error}" - } - try { - echo "${env_name} Test: remove pool network ${network_name}" - sh "docker network rm ${network_name}" - } catch (error) { - echo "${env_name} Test: error while delete ${network_name} - ${error}" + if (network_name != null) { + try { + sh "docker ps --format '{{.ID}}' --filter network=${network_name} | xargs docker rm -f" + } catch (error) { + echo "${env_name} Test: error while force clean-up network ${network_name} - ${error}" + } + try { + echo "${env_name} Test: remove pool network ${network_name}" + sh "docker network rm ${network_name}" + } catch (error) { + echo "${env_name} Test: error while delete ${network_name} - ${error}" + } } step([$class: 'WsCleanup']) } From bb6410fb679b6d01c3c92ed6431c49dd5d8bd046 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 14 Nov 2017 14:52:05 -0700 Subject: [PATCH 08/18] Updated version of rusqlcipher Signed-off-by: Michael Lodder --- libindy/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libindy/Cargo.toml b/libindy/Cargo.toml index c59a83c17f..148b05ef17 100644 --- a/libindy/Cargo.toml +++ b/libindy/Cargo.toml @@ -44,7 +44,7 @@ libc = "0.2.21" log = "0.3.7" openssl = { version = "0.9.11", optional = true } rand = "0.3" -rusqlcipher = { version = "0.14.3", features=["bundled"] } +rusqlcipher = { version = "0.14.4", features=["bundled"] } rust-base58 = {version = "0.0.4", optional = true} base64 = "0.6.0" serde = "1.0" From cde2f5cf7685145ed9ee0232c96ce17a451d7d8f Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 14 Nov 2017 15:29:25 -0700 Subject: [PATCH 09/18] Updated version Signed-off-by: Michael Lodder --- libindy/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libindy/Cargo.toml b/libindy/Cargo.toml index 148b05ef17..5753231d03 100644 --- a/libindy/Cargo.toml +++ b/libindy/Cargo.toml @@ -44,7 +44,7 @@ libc = "0.2.21" log = "0.3.7" openssl = { version = "0.9.11", optional = true } rand = "0.3" -rusqlcipher = { version = "0.14.4", features=["bundled"] } +rusqlcipher = { version = "0.14.5", features=["bundled"] } rust-base58 = {version = "0.0.4", optional = true} base64 = "0.6.0" serde = "1.0" From b7afc5faeb29f9fb2b6ae3341c35a7cd10fb3a1f Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 14 Nov 2017 15:55:06 -0700 Subject: [PATCH 10/18] Updated version Signed-off-by: Michael Lodder --- libindy/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libindy/Cargo.toml b/libindy/Cargo.toml index 5753231d03..617705d770 100644 --- a/libindy/Cargo.toml +++ b/libindy/Cargo.toml @@ -44,7 +44,7 @@ libc = "0.2.21" log = "0.3.7" openssl = { version = "0.9.11", optional = true } rand = "0.3" -rusqlcipher = { version = "0.14.5", features=["bundled"] } +rusqlcipher = { version = "0.14.6", features=["bundled"] } rust-base58 = {version = "0.0.4", optional = true} base64 = "0.6.0" serde = "1.0" From a3de182e0263f504ec50120ce3ffc998c62dcd1d Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Wed, 15 Nov 2017 14:07:07 +0300 Subject: [PATCH 11/18] [ios] Direct docker calls in iOS pipeline; fix iOS simulator version. Signed-off-by: Sergey Minaev --- Jenkinsfile.ci | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index ef7db0b707..2bd2c566ca 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -95,14 +95,13 @@ def macosTesting() { def iosTesting() { node('macos') { stage('iOS Test') { - def poolInst try { echo "iOS Test: Checkout scm" checkout scm echo "iOS Test: Running pool" - def poolEnv = dockerBuild('indy_pool', 'ci/indy-pool.dockerfile ci') - poolInst = poolEnv.run('-p 9701-9708:9701-9708') + sh "docker build -f ci/indy-pool.dockerfile -t indy_pool ci" + sh "docker run -d --network host --name indy_pool -p 9701-9708:9701-9708 indy_pool" dir('wrappers/ios/libindy-pod') { echo "iOS Test: Build" @@ -111,10 +110,18 @@ def iosTesting() { sh "pod install" echo "iOS Test: Testing" - sh "xcodebuild test -workspace Indy.xcworkspace -scheme Indy-demo -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=11.1'" + sh "xcodebuild test -workspace Indy.xcworkspace -scheme Indy-demo -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=10.3.1'" } } finally { - closePool("iOS Test", null, poolInst) + try { + sh "docker stop indy_pool" + } catch (ignore) { + } + try { + sh "docker rm indy_pool" + } catch (ignore) { + } + step([$class: 'WsCleanup']) } } } From f3b96766f394b378baf59f6f40ac0b6c25b6a756 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Wed, 15 Nov 2017 16:16:02 +0300 Subject: [PATCH 12/18] [ios] Add building libindy pod step to CI; fix appropriate build script. Signed-off-by: Sergey Minaev --- Jenkinsfile.ci | 7 +++++++ libindy/build-libindy-ios.sh | 30 +++++++----------------------- 2 files changed, 14 insertions(+), 23 deletions(-) mode change 100644 => 100755 libindy/build-libindy-ios.sh diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 2bd2c566ca..d4145fd86b 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -103,6 +103,13 @@ def iosTesting() { sh "docker build -f ci/indy-pool.dockerfile -t indy_pool ci" sh "docker run -d --network host --name indy_pool -p 9701-9708:9701-9708 indy_pool" + dir('libindy') { + echo 'iOS Test: build libindy pod' + sh './build-libindy-ios.sh' + } + + //TODO use local build pod for wrapper test + dir('wrappers/ios/libindy-pod') { echo "iOS Test: Build" diff --git a/libindy/build-libindy-ios.sh b/libindy/build-libindy-ios.sh old mode 100644 new mode 100755 index 347d900966..b3079885bd --- a/libindy/build-libindy-ios.sh +++ b/libindy/build-libindy-ios.sh @@ -1,18 +1,16 @@ -#!/bin/sh +#!/bin/sh -e export PKG_CONFIG_ALLOW_CROSS=1 export OPENSSL_DIR=/usr/local/Cellar/openssl/1.0.2l -export EVERNYM_REPO_KEY=~/Documents/EvernymRepo -export LIBINDY_POD_VERSION=0.0.3 export POD_FILE_NAME=libindy.tar.gz -echo "\nBuild IOS POD started..." +echo "Build IOS POD started..." cargo lipo echo 'Build completed successfully.' -WORK_DIR=`mktemp -d` - -echo "Try to create temporary directory: $WORK_DIR" +WORK_DIR="out_libindy_pod" +echo "Try to create out directory: $WORK_DIR" +mkdir $WORK_DIR if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then echo "Could not create temp dir $WORK_DIR" @@ -28,21 +26,7 @@ cd $WORK_DIR tar -cvzf $POD_FILE_NAME * ls -l $WORK_DIR/$POD_FILE_NAME -echo "\nPacking completed." +echo "Packing completed." cd $CUR_DIR -#echo "Uploading...." - -#cat < Date: Wed, 15 Nov 2017 16:52:36 +0300 Subject: [PATCH 13/18] Fix warning for compilation libindy on MacOS. Signed-off-by: Sergey Minaev --- libindy/src/services/pool/catchup.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libindy/src/services/pool/catchup.rs b/libindy/src/services/pool/catchup.rs index 088a22dc91..a682bc55ea 100644 --- a/libindy/src/services/pool/catchup.rs +++ b/libindy/src/services/pool/catchup.rs @@ -209,7 +209,7 @@ impl CatchupHandler { } fn catchup_step(&mut self, catchup: CatchupRep, node_idx: usize) -> Result { - let mut process = self.pending_catchup.as_mut() + let process = self.pending_catchup.as_mut() .ok_or(CommonError::InvalidState("Process non-existing CatchUp".to_string()))?; process.pending_reps.push((catchup, node_idx)); From 990c024615ef82ed240cfe6ea26dc8ab58dad814 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Wed, 15 Nov 2017 17:12:52 +0300 Subject: [PATCH 14/18] [ios] Clean-up building script for libindy pod. Signed-off-by: Sergey Minaev --- libindy/build-libindy-ios.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libindy/build-libindy-ios.sh b/libindy/build-libindy-ios.sh index b3079885bd..53e06ef7cc 100755 --- a/libindy/build-libindy-ios.sh +++ b/libindy/build-libindy-ios.sh @@ -17,16 +17,15 @@ if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then exit 1 fi -echo "Packing...\n\n" +echo "Packing..." cp include/*.h $WORK_DIR cp target/universal/debug/libindy.a $WORK_DIR -CUR_DIR=`pwd` cd $WORK_DIR tar -cvzf $POD_FILE_NAME * +cd - ls -l $WORK_DIR/$POD_FILE_NAME echo "Packing completed." -cd $CUR_DIR echo "Out directory: $WORK_DIR" From 9b41936fcdc9473266b05feb7d9e0d1b265eefed Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Wed, 15 Nov 2017 20:01:02 +0300 Subject: [PATCH 15/18] [ios] Add hack to test iOS wrappers at just built libindy pod Signed-off-by: Sergey Minaev --- Jenkinsfile.ci | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index d4145fd86b..deba3403a1 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -108,14 +108,16 @@ def iosTesting() { sh './build-libindy-ios.sh' } - //TODO use local build pod for wrapper test - dir('wrappers/ios/libindy-pod') { - echo "iOS Test: Build" - echo "iOS Test: Installing dependencies (pods)" sh "pod install" + } + // FIXME replace this hack (manually rewrite installed pod) + sh "rm -f wrappers/ios/libindy-pod/Pods/libindy/*.[ah]" + sh "cp libindy/out_libindy_pod/*.[ah] wrappers/ios/libindy-pod/Pods/libindy" + + dir('wrappers/ios/libindy-pod') { echo "iOS Test: Testing" sh "xcodebuild test -workspace Indy.xcworkspace -scheme Indy-demo -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=10.3.1'" } From a7e135454407b0a5867fb065f0b93cf969c920e1 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Fri, 12 Jan 2018 12:53:41 +0300 Subject: [PATCH 16/18] Increment versions to 1.3.0. Signed-off-by: Sergey Minaev --- libindy/Cargo.lock | 2 +- libindy/Cargo.toml | 2 +- libindy/debian/changelog | 4 ++-- wrappers/ios/libindy-pod/Podfile | 2 +- wrappers/java/pom.xml | 2 +- wrappers/python/setup.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libindy/Cargo.lock b/libindy/Cargo.lock index e79432f100..a7bab73aac 100644 --- a/libindy/Cargo.lock +++ b/libindy/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "indy" -version = "1.2.0" +version = "1.3.0" dependencies = [ "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/libindy/Cargo.toml b/libindy/Cargo.toml index b07764c42c..c53a86078c 100644 --- a/libindy/Cargo.toml +++ b/libindy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "indy" -version = "1.2.0" +version = "1.3.0" authors = [ "Sergej Pupykin ", "Vyacheslav Gudkov ", diff --git a/libindy/debian/changelog b/libindy/debian/changelog index 712ffb9378..d833ecad62 100644 --- a/libindy/debian/changelog +++ b/libindy/debian/changelog @@ -1,4 +1,4 @@ -libindy (1.2.0) unstable; urgency=medium +libindy (1.3.0) unstable; urgency=medium [ Hyperledger ] - * indy_key_for_local_did added + * encryption option for default wallet is added diff --git a/wrappers/ios/libindy-pod/Podfile b/wrappers/ios/libindy-pod/Podfile index 36688edd2e..409c616bce 100644 --- a/wrappers/ios/libindy-pod/Podfile +++ b/wrappers/ios/libindy-pod/Podfile @@ -9,7 +9,7 @@ def appPods pod 'libzmq-pw',"4.2.2" pod 'OpenSSL' pod 'milagro', "3.0.0" - pod 'libindy', "1.2.0" + pod 'libindy', "1.3.0" end target 'Indy-demo' do diff --git a/wrappers/java/pom.xml b/wrappers/java/pom.xml index fc0121355f..0173f4455f 100644 --- a/wrappers/java/pom.xml +++ b/wrappers/java/pom.xml @@ -5,7 +5,7 @@ org.hyperledger indy jar - 1.2.0 + 1.3.0 indy This is the official SDK for Hyperledger Indy (https://www.hyperledger.org/projects), which provides a distributed-ledger-based foundation for self-sovereign identity (https://sovrin.org). diff --git a/wrappers/python/setup.py b/wrappers/python/setup.py index d5771ff89c..1c17b378da 100644 --- a/wrappers/python/setup.py +++ b/wrappers/python/setup.py @@ -2,7 +2,7 @@ setup( name='python3-indy', - version='1.2.0', + version='1.3.0', packages=['indy'], url='https://github.com/hyperledger/indy-sdk', license='MIT/Apache-2.0', From d4b2e567129f94f9e6138b216f5088ac5190e416 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Fri, 12 Jan 2018 13:07:21 +0300 Subject: [PATCH 17/18] Add iOS podspecs for 1.3.0 build. Signed-off-by: Sergey Minaev --- .../1.3.0/libindy-objc.podspec.json | 23 +++++++++++++++++++ Specs/libindy/1.3.0/libindy.podspec.json | 23 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 Specs/libindy-objc/1.3.0/libindy-objc.podspec.json create mode 100644 Specs/libindy/1.3.0/libindy.podspec.json diff --git a/Specs/libindy-objc/1.3.0/libindy-objc.podspec.json b/Specs/libindy-objc/1.3.0/libindy-objc.podspec.json new file mode 100644 index 0000000000..2b72e1e4e4 --- /dev/null +++ b/Specs/libindy-objc/1.3.0/libindy-objc.podspec.json @@ -0,0 +1,23 @@ +{ + "name": "libindy-objc", + "version": "1.3.0", + "summary": "Summary TODO.", + "homepage": "TODO", + "license": { + "type": "Apache License 2.0", + "file": "LICENSE" + }, + "authors": { + "Daniel Hardman": "daniel.hardman@evernym.com" + }, + "source": { + "http": "https://repo.sovrin.org/ios/libindy/stable/indy-objc/1.3.0/libindy-objc.zip" + }, + "platforms": { + "ios": "10.0" + }, + "ios": { + "vendored_frameworks": "libindy-objc/Indy.framework" + }, + "module_name": "Indy" +} diff --git a/Specs/libindy/1.3.0/libindy.podspec.json b/Specs/libindy/1.3.0/libindy.podspec.json new file mode 100644 index 0000000000..e7958a9f4c --- /dev/null +++ b/Specs/libindy/1.3.0/libindy.podspec.json @@ -0,0 +1,23 @@ +{ + "name": "libindy", + "version": "1.3.0", + "summary": "Summary TODO.", + "description": "Description TODO.", + "homepage": "TODO", + "license": { + "type": "Apache License 2.0", + "file": "LICENSE" + }, + "authors": { + "Daniel Hardman": "daniel.hardman@evernym.com" + }, + "platforms": { + "ios": "10.0" + }, + "source": { + "http": "https://repo.sovrin.org/ios/libindy/stable/libindy-core/1.3.0/libindy.tar.gz" + }, + "source_files": "*.h", + "vendored_libraries": "*.a", + "requires_arc": false +} From 42206af859ccb800a6426a8183ab1ee9824f32c0 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Fri, 12 Jan 2018 13:12:57 +0300 Subject: [PATCH 18/18] Temporary disable incomplete iOS build only for this RC. Signed-off-by: Sergey Minaev --- Jenkinsfile.ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index deba3403a1..1176e8602e 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -7,7 +7,7 @@ def testing() { parallel([ 'ubuntu-test' : { ubuntuTesting() }, 'macos-test' : { macosTesting() }, - 'ios-test' : { iosTesting() }, +// 'ios-test' : { iosTesting() }, 'redhat-test' : { rhelTesting() }, 'windows-test': { windowsTesting() } ])