From 5e34da20f437f5f9e0420935cf15969b93880823 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 26 Mar 2019 14:31:53 +0300 Subject: [PATCH 01/33] ST-492 Updated Libsovtoken dependencies Signed-off-by: artem.ivanov --- libsovtoken/Cargo.toml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libsovtoken/Cargo.toml b/libsovtoken/Cargo.toml index c8329deb0..35f731372 100644 --- a/libsovtoken/Cargo.toml +++ b/libsovtoken/Cargo.toml @@ -21,21 +21,21 @@ crate-type = ["staticlib", "rlib", "cdylib"] [dependencies] bs58 = {version="0.2.2", features = ["check"]} -base64 = "0.6.0" +base64 = "0.10.1" hex = "0.2.0" -lazy_static = "0.2" +lazy_static = "1.3.0" libc = "0.2.41" -log = "0.4.1" -openssl = "0.10" -rand = "0.4.2" +log = "0.4.6" +openssl = "0.10.20" +rand = "0.3" indy-sys = "1.8.1" indy = "1.8.1" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" -sha2 = "0.6.0" -sha3 = "0.6.0" -sodiumoxide = {version = "0.0.14"} +serde = "1.0.89" +serde_derive = "1.0.89" +serde_json = "1.0.39" +sha2 = "0.8.0" +sha3 = "0.8.0" +sodiumoxide = "0.0.16" [dev-dependencies] dirs = "1.0.4" From 3f4fcce9361cf9bc7649ca915c32615e0872d8a7 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 2 Apr 2019 08:33:36 +0300 Subject: [PATCH 02/33] ST-492 Updated Indy version Signed-off-by: artem.ivanov --- libsovtoken/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsovtoken/Cargo.toml b/libsovtoken/Cargo.toml index f91b72e18..7029ac168 100644 --- a/libsovtoken/Cargo.toml +++ b/libsovtoken/Cargo.toml @@ -28,8 +28,8 @@ libc = "0.2.41" log = "0.4.6" openssl = "0.10.20" rand = "0.3" -indy-sys = "1.8.1" -indy = "1.8.1" +indy-sys = "1.8.2" +indy = "1.8.2" serde = "1.0.89" serde_derive = "1.0.89" serde_json = "1.0.39" From 6f2ddd0c0a95baa491c2942749a63bc52866e76c Mon Sep 17 00:00:00 2001 From: Matt Raffel Date: Thu, 4 Apr 2019 09:17:41 -0600 Subject: [PATCH 03/33] adds initial file Signed-off-by: Matt Raffel --- doc/building.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 doc/building.md diff --git a/doc/building.md b/doc/building.md new file mode 100644 index 000000000..bfcaab8ec --- /dev/null +++ b/doc/building.md @@ -0,0 +1,49 @@ +Building Libsovtoken + + +## Windows Builds +### Prerequisites +Visual Studio, git, etc + + +### Step 1 +Start with following the directions for building indy sdk: + +https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md + +#### Step 1 Notes +some differences in what I did: +downloaded openssl from here: https://slproweb.com/products/Win32OpenSSL.html. When prompted for where the libraries should go, I chose bin directory + + +### Step 2 +For this example +- all libraries and prebuilt prebuilt indy-sdk dependencies was put in `d:\engineering\libs` +- during open ssl install, selected the option install opensll in bin sub-directory + +Set the following environment variables: +``` +SET OPENSSL_DIR=C:\PROGRA~1\OPENSS~1\ +SET X86_64_PC_WINDOWS_MSVC_OPENSSL_LIB_DIR=%OPENSSL_DIR%lib +SET OPENSSL_INCLUDE_DIR=%OPENSSL_DIR%include +SET X86_64_PC_WINDOWS_MSVC_OPENSSL_INCLUDE_DIR=%OPENSSL_DIR%include +SET SODIUM_LIB_DIR=d:\engineering\libs +SET SODIUM_STATIC=d:\engineering\libs\lib +SET LIBINDY_DIR=d:\engineering\libs +SET INDY_PREBUILT_DEPS_DIR=d:\engineering\libs + +SET INDY_PREBUILT_DEPS_DIR=d:\engineering\libs +SET INDY_CRYPTO_PREBUILT_DEPS_DIR=d:\engineering\libs +SET MILAGRO_DIR=d:\engineering\libs +SET LIBZMQ_PREFIX=d:\engineering\libs +``` + +#### Step 2 notes +Use short file names and short directory names. There seemed to be some problems with long names. + + +### Step 3 (optional) +build indy-sdk (if you can get the windows build of indy-sdk then you can skip this) using the standard cargo build command and copied dll and lib to d:\engineering\libs + +### Step 4 +build libsovtoken using the standard `cargo build` command From bbebc2671d2ae67b7a6a8506f7f055d8c1ed558a Mon Sep 17 00:00:00 2001 From: Matt Raffel Date: Thu, 4 Apr 2019 09:36:35 -0600 Subject: [PATCH 04/33] making pr Signed-off-by: Matt Raffel --- doc/building.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/doc/building.md b/doc/building.md index bfcaab8ec..b3cde55b6 100644 --- a/doc/building.md +++ b/doc/building.md @@ -3,20 +3,22 @@ Building Libsovtoken ## Windows Builds ### Prerequisites -Visual Studio, git, etc +- Visual Studio, rust, git, etc...are installed +- rust builds demo project -### Step 1 -Start with following the directions for building indy sdk: +### Step 1 Preparation +Start with reading the directions for [building indy sdk on windows](https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md). -https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md +The most important step is downloading the prebuilt dependencies (unless you want to build them yourself). + +Building LibIndy is not required if you are able to download the prebuilt LibIndy libraries. Suggestion is to start [here](https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md#build) and work backward if there are any problems. #### Step 1 Notes -some differences in what I did: -downloaded openssl from here: https://slproweb.com/products/Win32OpenSSL.html. When prompted for where the libraries should go, I chose bin directory +Downloaded openssl from [here](https://slproweb.com/products/Win32OpenSSL.html). See notes below about installation configuration. -### Step 2 +### Step 2 Environment Configuration For this example - all libraries and prebuilt prebuilt indy-sdk dependencies was put in `d:\engineering\libs` - during open ssl install, selected the option install opensll in bin sub-directory @@ -39,11 +41,13 @@ SET LIBZMQ_PREFIX=d:\engineering\libs ``` #### Step 2 notes -Use short file names and short directory names. There seemed to be some problems with long names. - +- Use short file names and short directory names for the SSL configuration. There seemed to be some problems with long names. +- Alternatively: if you chose to build libindy, set `LIBINDY_DIR` to the build output directory. +This is typically `{libindy source directory}\target\[debug | release]` ### Step 3 (optional) -build indy-sdk (if you can get the windows build of indy-sdk then you can skip this) using the standard cargo build command and copied dll and lib to d:\engineering\libs +build indy-sdk (if you can get the windows build of indy-sdk then you can skip this) using the standard `cargo build` command and, +if necessary, copy dll and lib to `LIBINDY_DIR` -### Step 4 +### Step 4 Building Libsovtoken build libsovtoken using the standard `cargo build` command From 7b3e3014c789728d6587aebcdaef91d785adff54 Mon Sep 17 00:00:00 2001 From: Matt Raffel Date: Thu, 4 Apr 2019 09:44:33 -0600 Subject: [PATCH 05/33] removing duplicate word Signed-off-by: Matt Raffel --- doc/building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/building.md b/doc/building.md index b3cde55b6..49a28e4bd 100644 --- a/doc/building.md +++ b/doc/building.md @@ -20,7 +20,7 @@ Downloaded openssl from [here](https://slproweb.com/products/Win32OpenSSL.html). ### Step 2 Environment Configuration For this example -- all libraries and prebuilt prebuilt indy-sdk dependencies was put in `d:\engineering\libs` +- all libraries and prebuilt indy-sdk dependencies was put in `d:\engineering\libs` - during open ssl install, selected the option install opensll in bin sub-directory Set the following environment variables: From 3f74f8f41044f5458d050e3bca68c2086a802d6b Mon Sep 17 00:00:00 2001 From: Matt Raffel Date: Thu, 4 Apr 2019 09:48:34 -0600 Subject: [PATCH 06/33] format change Signed-off-by: Matt Raffel --- doc/building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/building.md b/doc/building.md index 49a28e4bd..81333d3d6 100644 --- a/doc/building.md +++ b/doc/building.md @@ -1,4 +1,4 @@ -Building Libsovtoken +# Building Libsovtoken ## Windows Builds From 26b118be7d51e25860e196d8926e9e83fa6e5253 Mon Sep 17 00:00:00 2001 From: Matt Raffel Date: Fri, 5 Apr 2019 10:34:14 -0600 Subject: [PATCH 07/33] fixed typos Signed-off-by: Matt Raffel --- doc/building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/building.md b/doc/building.md index 81333d3d6..76dffc103 100644 --- a/doc/building.md +++ b/doc/building.md @@ -21,7 +21,7 @@ Downloaded openssl from [here](https://slproweb.com/products/Win32OpenSSL.html). ### Step 2 Environment Configuration For this example - all libraries and prebuilt indy-sdk dependencies was put in `d:\engineering\libs` -- during open ssl install, selected the option install opensll in bin sub-directory +- during openssl install, selected the option install openssl in bin sub-directory Set the following environment variables: ``` From fc6b02d6d8c851f700e99e1d791189ecc4b30498 Mon Sep 17 00:00:00 2001 From: Sergey Minaev Date: Mon, 8 Apr 2019 12:44:49 +0300 Subject: [PATCH 08/33] Update dependency on libindy Signed-off-by: Sergey Minaev --- devops/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops/Makefile b/devops/Makefile index 0ed194cfd..6084d86c1 100644 --- a/devops/Makefile +++ b/devops/Makefile @@ -45,7 +45,7 @@ FPM_P_VENDOR := Sovrin FPM_P_DESCRIPTION := libsovtoken written in Rust FPM_P_NAME = $(PACKAGE_NAME) FPM_P_VERSION ?= $(SRC_VERSION) -FPM_P_DEPENDS = libindy(>=1.8.2) +FPM_P_DEPENDS = libindy(>=1.8.2~1045) FPM_P_OUTPUT_DIR = $(LIB_TARGET_DIR) FPM_ARGS = $(LIB_DYNAMIC)=/usr/lib/ From f309d9350eafd9616fec48956fdc69418245b83b Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 10 Apr 2019 15:32:17 +0300 Subject: [PATCH 09/33] ST-315 Simplified documentation for building on windows Signed-off-by: artem.ivanov --- README.md | 3 ++ doc/build-guides/windows-build.md | 21 ++++++++++++ doc/building.md | 53 ------------------------------- libsovtoken/build.rs | 21 ++++++------ 4 files changed, 36 insertions(+), 62 deletions(-) create mode 100644 doc/build-guides/windows-build.md delete mode 100644 doc/building.md diff --git a/README.md b/README.md index 41677adab..e890fe3b8 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,9 @@ Adds Sovrin's token functionality to HyperLedger's Indy-SDK. 1. cargo test +### How to build Libsovtoken from source +* [Windows](doc/build-guides/windows-build.md) + ## How To Contribute diff --git a/doc/build-guides/windows-build.md b/doc/build-guides/windows-build.md new file mode 100644 index 000000000..91ff760a2 --- /dev/null +++ b/doc/build-guides/windows-build.md @@ -0,0 +1,21 @@ +# Building Libsovtoken for Windows + +### Step 1 Build Liibndy +Go through [indy sdk on windows build documentation](https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md) to get libindy artifacts. +The most important steps are: +* [Downloading of the Indy prebuilt dependencies](https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md#getbuild-dependencies) +* [Libindy building]( https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md#build) + +### Step 2 Environment Configuration +For this example +- all libraries and prebuilt indy-sdk dependencies was put in `C:\BIN\x64` + +Set the following environment variables: +``` +SET OPENSSL_DIR=C:\BIN\x64 +SET SODIUM_LIB_DIR=C:\BIN\x64\lib +SET LIBINDY_DIR={libindy source directory}\target\[debug | release] +``` + +### Step 4 Building Libsovtoken +Build libsovtoken using the standard `cargo build` command diff --git a/doc/building.md b/doc/building.md deleted file mode 100644 index 76dffc103..000000000 --- a/doc/building.md +++ /dev/null @@ -1,53 +0,0 @@ -# Building Libsovtoken - - -## Windows Builds -### Prerequisites -- Visual Studio, rust, git, etc...are installed -- rust builds demo project - - -### Step 1 Preparation -Start with reading the directions for [building indy sdk on windows](https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md). - -The most important step is downloading the prebuilt dependencies (unless you want to build them yourself). - -Building LibIndy is not required if you are able to download the prebuilt LibIndy libraries. Suggestion is to start [here](https://github.com/hyperledger/indy-sdk/blob/master/docs/build-guides/windows-build.md#build) and work backward if there are any problems. - -#### Step 1 Notes -Downloaded openssl from [here](https://slproweb.com/products/Win32OpenSSL.html). See notes below about installation configuration. - - -### Step 2 Environment Configuration -For this example -- all libraries and prebuilt indy-sdk dependencies was put in `d:\engineering\libs` -- during openssl install, selected the option install openssl in bin sub-directory - -Set the following environment variables: -``` -SET OPENSSL_DIR=C:\PROGRA~1\OPENSS~1\ -SET X86_64_PC_WINDOWS_MSVC_OPENSSL_LIB_DIR=%OPENSSL_DIR%lib -SET OPENSSL_INCLUDE_DIR=%OPENSSL_DIR%include -SET X86_64_PC_WINDOWS_MSVC_OPENSSL_INCLUDE_DIR=%OPENSSL_DIR%include -SET SODIUM_LIB_DIR=d:\engineering\libs -SET SODIUM_STATIC=d:\engineering\libs\lib -SET LIBINDY_DIR=d:\engineering\libs -SET INDY_PREBUILT_DEPS_DIR=d:\engineering\libs - -SET INDY_PREBUILT_DEPS_DIR=d:\engineering\libs -SET INDY_CRYPTO_PREBUILT_DEPS_DIR=d:\engineering\libs -SET MILAGRO_DIR=d:\engineering\libs -SET LIBZMQ_PREFIX=d:\engineering\libs -``` - -#### Step 2 notes -- Use short file names and short directory names for the SSL configuration. There seemed to be some problems with long names. -- Alternatively: if you chose to build libindy, set `LIBINDY_DIR` to the build output directory. -This is typically `{libindy source directory}\target\[debug | release]` - -### Step 3 (optional) -build indy-sdk (if you can get the windows build of indy-sdk then you can skip this) using the standard `cargo build` command and, -if necessary, copy dll and lib to `LIBINDY_DIR` - -### Step 4 Building Libsovtoken -build libsovtoken using the standard `cargo build` command diff --git a/libsovtoken/build.rs b/libsovtoken/build.rs index feffe40b6..7225c1b3f 100644 --- a/libsovtoken/build.rs +++ b/libsovtoken/build.rs @@ -11,6 +11,18 @@ fn main() { Err(..) => panic!("Missing required environment variable LIBINDY_DIR") }; + let target = env::var("TARGET").unwrap(); + println!("target={}", target); + + if target.find("-windows-").is_some() { + println!("cargo:rustc-link-lib=indy.dll"); + println!("indy_dir={}", libindy_lib_path); + let libindy_lib_path = Path::new(libindy_lib_path.as_str()); + + println!("cargo:rustc-flags=-L {}", libindy_lib_path.as_os_str().to_str().unwrap()); + return; + } + println!("cargo:rustc-link-search=native={}",libindy_lib_path); if let Ok(_mode) = env::var("LIBINDY_STATIC") { @@ -19,8 +31,6 @@ fn main() { println!("cargo:rustc-link-lib=dylib=indy"); } - let target = env::var("TARGET").unwrap(); - println!("target={}", target); if target.contains("linux-android") { let openssl = match env::var("OPENSSL_LIB_DIR") { @@ -41,12 +51,5 @@ fn main() { println!("cargo:rustc-link-lib=dylib=ssl"); println!("cargo:rustc-link-search=native={}", sodium); println!("cargo:rustc-link-lib=static=sodium"); - }else if target.find("-windows-").is_some() { - println!("cargo:rustc-link-lib=dylib=ssleay32"); - println!("cargo:rustc-link-lib=dylib=zmq"); - println!("cargo:rustc-link-lib=dylib=sodium"); - let prebuilt_dir = env::var("INDY_PREBUILT_DEPS_DIR").unwrap(); - println!("cargo:rustc-flags=-L {}\\lib", prebuilt_dir); - return; } } From a7945a4eae361c1723c71a28d9e3b3786896db5d Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 17 Apr 2019 09:51:59 +0300 Subject: [PATCH 10/33] Updated request serialization to match libindy's Signed-off-by: artem.ivanov --- libsovtoken/src/logic/xfer_payload.rs | 77 +++++++++++--------- libsovtoken/src/utils/constants/txn_types.rs | 13 ++-- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/libsovtoken/src/logic/xfer_payload.rs b/libsovtoken/src/logic/xfer_payload.rs index ada0d19d9..5d47ee8ff 100644 --- a/libsovtoken/src/logic/xfer_payload.rs +++ b/libsovtoken/src/logic/xfer_payload.rs @@ -20,8 +20,9 @@ use ErrorCode; use logic::address; use logic::indy_sdk_api::crypto_api::CryptoAPI; use logic::input::{Input, Inputs}; -use logic::output::{Outputs}; +use logic::output::Outputs; use logic::hash::Hash; +use utils::constants::txn_types::{ATTRIB, GET_ATTRIB}; /** * Holds `inputs` and `outputs` @@ -62,9 +63,11 @@ pub struct XferPayload { } unsafe impl Send for XferPayload {} + unsafe impl Sync for XferPayload {} impl InputSigner for XferPayload {} + impl XferPayload { pub fn new(inputs: Inputs, outputs: Outputs, extra: Option) -> Self { @@ -110,7 +113,7 @@ impl XferPayload { debug!("Indicator stripped from inputs"); - XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(),Box::new(move |signatures| { + XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), Box::new(move |signatures| { match signatures { Ok(signatures) => { let payload = Self::clone_payload_add_signatures(&self, signatures); @@ -136,7 +139,7 @@ impl XferPayload { .filter(|signature| signature.is_some()) .map(|signature| signature.unwrap().to_owned()) .collect(); - + XferPayload { inputs: prev.inputs.clone(), outputs: prev.outputs.clone(), @@ -204,7 +207,7 @@ trait InputSigner { Some(json!([input])), Some(json!(outputs)), txn_digest.clone().map(|e| json!(e)), -// _extra.map(|e| json!(e)) + // _extra.map(|e| json!(e)) ].into_iter().filter_map(|e| e).collect(); let message = serialize_signature(json!(vals))?; @@ -236,24 +239,21 @@ trait InputSigner { } pub fn serialize_signature(v: serde_json::Value) -> Result { - do_serialize_signature(v, true) + let _type = v["operation"]["type"].clone(); + do_serialize_signature(v, true, _type.as_str()) } -fn do_serialize_signature(v: serde_json::Value, is_top_level: bool) -> Result { +fn do_serialize_signature(v: serde_json::Value, is_top_level: bool, _type: Option<&str>) -> Result { match v { serde_json::Value::Bool(value) => Ok(if value { "True".to_string() } else { "False".to_string() }), serde_json::Value::Number(value) => Ok(value.to_string()), serde_json::Value::String(value) => Ok(value), serde_json::Value::Array(array) => { - let mut result = "".to_string(); - let length = array.len(); - for (index, element) in array.iter().enumerate() { - result += &do_serialize_signature(element.clone(), false)?; - if index < length - 1 { - result += ","; - } - } - Ok(result) + array + .into_iter() + .map(|element| do_serialize_signature(element, false, _type)) + .collect::, ErrorCode>>() + .map(|res| res.join(",")) } serde_json::Value::Object(map) => { let mut result = "".to_string(); @@ -267,12 +267,19 @@ fn do_serialize_signature(v: serde_json::Value, is_top_level: bool) -> Result (Inputs, Outputs) { let outputs = vec![ Output::new(String::from("TKe9eXtchV71J2qXX5HwP8rbkTBStnEEkMwQkHie265VtRSbs"), 10), @@ -314,7 +321,7 @@ mod test_xfer_payload { let inputs = vec![ Input::new(String::from("E9LNHk8shQ6xe2RfydzXDSsyhWC6vJaUeKE2mmc6mWraDfmKm"), 1), Input::new(String::from("2oWxuFMbhPewEbCEeKnvjcpVq8qpHHrN5y4aU81MWG5dYfeM7V"), 1), - ]; + ]; return (inputs, outputs); } @@ -335,7 +342,7 @@ mod test_xfer_payload { sender.lock().unwrap().send(result).unwrap(); }; XferPayload::sign_input( - &CryptoApiHandler{}, + &CryptoApiHandler {}, wallet_handle, input, outputs, @@ -352,7 +359,7 @@ mod test_xfer_payload { let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::sign_inputs(&CryptoApiHandler{}, wallet_handle, inputs, outputs, &None, &None, + XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, Box::new(cb))?; receiver.recv().unwrap().map(|map| map.values().cloned().collect()) } @@ -380,7 +387,7 @@ mod test_xfer_payload { fn sign_multi_input_invalid_input_address() { let (mut inputs, outputs) = inputs_outputs_valid(); String::remove(&mut inputs[0].address, 5); - + let signatures = sign_inputs_sync(&inputs, &outputs).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signatures); } @@ -388,7 +395,7 @@ mod test_xfer_payload { #[test] fn sign_multi_input() { let (inputs, outputs) = inputs_outputs_valid(); - + let signed_inputs = sign_inputs_sync(&inputs, &outputs).unwrap(); assert!(signed_inputs.contains(&"31VzUm5vZRfWPk38W3YJaNjrkUeD6tELmjxv42cp7Vnksigned".to_string())); assert!(signed_inputs.contains(&"GyPZzuu8S1KMs5p6iE1wBzjQsFtaB7eigssW4YbdXdtesigned".to_string())); @@ -404,7 +411,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = payload.sign_transfer(&CryptoApiHandler{}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = payload.sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -418,7 +425,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler{}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -431,7 +438,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_transfer(&CryptoApiHandler{}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -444,7 +451,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_transfer(&CryptoApiHandler{}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -457,7 +464,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_fees(&CryptoApiHandler{}, wallet_handle, &None, Box::new(cb)); + let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_fees(&CryptoApiHandler {}, wallet_handle, &None, Box::new(cb)); assert!(signed_payload.is_ok()); } @@ -470,7 +477,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, outputs, None).sign_fees(&CryptoApiHandler{}, wallet_handle, &None, Box::new(cb)); + let signed_payload = XferPayload::new(inputs, outputs, None).sign_fees(&CryptoApiHandler {}, wallet_handle, &None, Box::new(cb)); assert!(signed_payload.is_ok()); } @@ -483,7 +490,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_fees(&CryptoApiHandler{}, wallet_handle, &None, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_fees(&CryptoApiHandler {}, wallet_handle, &None, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -505,13 +512,13 @@ mod test_xfer_payload { ]; let expected_signatures = Some(vec![String::from("31VzUm5vZRfWPk38W3YJaNjrkUeD6tELmjxv42cp7Vnksigned"), - String::from("GyPZzuu8S1KMs5p6iE1wBzjQsFtaB7eigssW4YbdXdtesigned")]); + String::from("GyPZzuu8S1KMs5p6iE1wBzjQsFtaB7eigssW4YbdXdtesigned")]); let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler{}, wallet_handle, Box::new(cb)).unwrap(); + XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap(); let signed_payload = receiver.recv().unwrap().unwrap(); assert_eq!(expected_inputs, signed_payload.inputs); @@ -527,7 +534,7 @@ mod test_xfer_payload { fn sign_multi_input_preserve_ordering() { let attempts = 5; let wallet_handle = 1; - let (mut inputs, outputs) = inputs_outputs_valid_qualified(); + let (mut inputs, outputs) = inputs_outputs_valid_qualified(); inputs.reverse(); let expected_signatures = vec![ @@ -543,7 +550,7 @@ mod test_xfer_payload { let sender = sender.clone(); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; payload.clone().sign_transfer( - &CryptoApiHandler{}, + &CryptoApiHandler {}, wallet_handle, Box::new(cb) ).unwrap(); diff --git a/libsovtoken/src/utils/constants/txn_types.rs b/libsovtoken/src/utils/constants/txn_types.rs index 1212625ed..1761551c3 100644 --- a/libsovtoken/src/utils/constants/txn_types.rs +++ b/libsovtoken/src/utils/constants/txn_types.rs @@ -29,14 +29,15 @@ pub const GET_UTXO: &'static str = "10002"; pub const SET_FEES: &'static str = "20000"; +pub const NYM: &'static str = "1"; + +pub const ATTRIB: &'static str = "100"; + +pub const GET_ATTRIB: &'static str = "104"; + /** #description A transaction type submitted by anyone to get the current Fees costs of every transaction */ -pub const GET_FEES: &'static str = "20001"; - - -pub const NYM: &'static str = "1"; - -pub const ATTRIB: &'static str = "100"; +pub const GET_FEES: &'static str = "20001"; \ No newline at end of file From cc175d9aa3aa9aaa89d6cc849d0769c0f4bb0e38 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 22 Apr 2019 10:23:36 +0300 Subject: [PATCH 11/33] ST-316: Initial version of windows CI pipeline Signed-off-by: artem.ivanov --- devops/aws-codebuild/Jenkinsfile.cd | 97 +++++++++++++++++++++++++++- devops/aws-codebuild/Jenkinsfile.ci | 76 ++++++++++++++++++++++ devops/windows/win-zip-and-upload.sh | 44 +++++++++++++ 3 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 devops/windows/win-zip-and-upload.sh diff --git a/devops/aws-codebuild/Jenkinsfile.cd b/devops/aws-codebuild/Jenkinsfile.cd index f00bcff61..2298d6039 100644 --- a/devops/aws-codebuild/Jenkinsfile.cd +++ b/devops/aws-codebuild/Jenkinsfile.cd @@ -15,6 +15,8 @@ String srcVersion gitHubUserCredId = env.GITHUB_BOT_USER ?: 'sovbot-github' sovrinPackagingRepo = env.SOVRIN_PACKAGING_REPO ?: 'https://github.com/sovrin-foundation/sovrin-packaging' sovrinPackagingBranch = env.SOVRIN_PACKAGING_BRANCH ?: 'master' +LIBINDY_STREAM = "stable" +LIBINDY_VERSION = "1.8.2" def downloadPackagingUtils() { git branch: sovrinPackagingBranch, credentialsId: gitHubUserCredId, url: sovrinPackagingRepo @@ -25,6 +27,7 @@ def downloadPackagingUtils() { def nodeLabels = [ codeBuild: env.LIBSOVTOKEN_CODEBUILD_NODE_LABEL ?: 'codebuild', macos: env.LIBSOVTOKEN_MACOS_NODE_LABEL ?: 'macos', + windows: env.LIBSOVTOKEN_WINDOWS_NODE_LABEL ?: 'win2016', ] def codeBuildPipelines = { @@ -354,6 +357,86 @@ def macosUpload = { } } +def windowsOSPipeline = { + stage("Windows Testing") { + def ws_path = "workspace/${env.JOB_NAME}".replace(' ', '_') + ws(ws_path) { + try { + stage('Checkout sources from SCM') { + checkout scm + } + + stage('Setup dependencies'){ + setupRust() + + bat 'wget -O prebuilt.zip "https://repo.sovrin.org/windows/libindy/deps/indy-sdk-deps.zip"' + bat 'unzip prebuilt.zip -d prebuilt' + + bat "wget -O indy.zip \"https://repo.sovrin.org/windows/libindy/$LIBINDY_STREAM/$LIBINDY_VERSION/libindy_${LIBINDY_VERSION}.zip\"" + bat 'unzip indy.zip -d indy' + } + + stage('Run Indy pool') { + bat "docker -H $INDY_SDK_SERVER_IP build --build-arg pool_ip=$INDY_SDK_SERVER_IP -f devops/indy-pool/Dockerfile -t indy_pool devops/indy-pool/" + bat "docker -H $INDY_SDK_SERVER_IP run -d --network host --name indy_pool -p 9701-9708:9701-9708 indy_pool" + } + + stage('Testing'){ + dir('libsovtoken') { + echo "Libsovtoken Testing: Build" + withEnv([ + "OPENSSL_DIR=$WORKSPACE\\prebuilt", + "SODIUM_LIB_DIR=$WORKSPACE\\prebuilt\\lib", + "LIBINDY_DIR=$WORKSPACE\\indy\\lib", + "PATH=$WORKSPACE\\prebuilt\\lib;$WORKSPACE\\indy\\lib;$PATH", + "RUST_BACKTRACE=1" + ]) { + bat "cargo build --release" + bat "cargo test --release --no-run" + + echo "Libsovtoken Testing: Run tests" + withEnv([ + "RUST_TEST_THREADS=1", + "RUST_LOG=debug", + "TEST_POOL_IP=$INDY_SDK_SERVER_IP" + ]) { + bat "cargo test --release" + } + } + + stash includes: 'target/release/*.dll', name: 'windowsArtifact' + } + } + } finally { + try { + bat "docker -H $INDY_SDK_SERVER_IP stop indy_pool" + } catch (ignore) { + } + try { + bat "docker -H $INDY_SDK_SERVER_IP rm indy_pool" + } catch (ignore) { + } + cleanWs() + } + } + cleanWs() + } +} + +def windowsUpload = { + stage('Upload libsovtoken package to Sovrin repo') { + unstash name: "windowsArtifact" + + withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'repo_key')]) { + withEnv([ + "SOVRIN_REPO_HOST=$SOVRIN_REPO_HOST", + ]) { + sh "devops/windows/win-zip-and-upload.sh $srcVersion '${repo_key}' $env.BRANCH_NAME $env.BUILD_NUMBER" + } + } + } +} + pipelineWrapper({ //put code build containers inside a vpc under our dev account env.USE_VPC_CONFIG = true @@ -366,6 +449,10 @@ pipelineWrapper({ macos: [ build: macOSPipeline, nodeLabel: "$nodeLabels.macos" + ], + windows: [ + build: windowsOSPipeline, + nodeLabel: "$nodeLabels.windows" ] ] builds.failFast = false @@ -378,6 +465,10 @@ pipelineWrapper({ macosPublish: [ build: macosUpload, nodeLabel: "$nodeLabels.codeBuild" + ], + windowsPublish: [ + build: windowsUpload, + nodeLabel: "$nodeLabels.codeBuild" ] ] @@ -394,4 +485,8 @@ pipelineWrapper({ notifier.email() } } -}) \ No newline at end of file +}) + +def setupRust() { + shell("rustup default 1.32.0") +} \ No newline at end of file diff --git a/devops/aws-codebuild/Jenkinsfile.ci b/devops/aws-codebuild/Jenkinsfile.ci index e7818dae0..c485b4715 100644 --- a/devops/aws-codebuild/Jenkinsfile.ci +++ b/devops/aws-codebuild/Jenkinsfile.ci @@ -7,12 +7,83 @@ def sovLibrary = library(identifier: 'sovrin-aws-codebuild@master', retriever: m logger = sovLibrary.Logger.new(this) notifier = sovLibrary.Notifier.new(this) logger.setGlobalLevel('TRACE') +LIBINDY_STREAM = "stable" +LIBINDY_VERSION = "1.8.2" def nodeLabels = [ codeBuild: env.LIBSOVTOKEN_CODEBUILD_NODE_LABEL ?: 'codebuild', macos: env.LIBSOVTOKEN_MACOS_NODE_LABEL ?: 'macos', + windows: env.LIBSOVTOKEN_WINDOWS_NODE_LABEL ?: 'win2016', ] +def setupRust() { + shell("rustup default 1.32.0") +} + +def windowsOSPipeline = { + stage("Windows Testing") { + def ws_path = "workspace/${env.JOB_NAME}".replace(' ', '_') + ws(ws_path) { + try { + stage('Checkout sources from SCM') { + checkout scm + } + + stage('Setup dependencies'){ + setupRust() + + bat 'wget -O prebuilt.zip "https://repo.sovrin.org/windows/libindy/deps/indy-sdk-deps.zip"' + bat 'unzip prebuilt.zip -d prebuilt' + + bat "wget -O indy.zip \"https://repo.sovrin.org/windows/libindy/$LIBINDY_STREAM/$LIBINDY_VERSION/libindy_${LIBINDY_VERSION}.zip\"" + bat 'unzip indy.zip -d indy' + } + + stage('Run Indy pool') { + bat "docker -H $INDY_SDK_SERVER_IP build --build-arg pool_ip=$INDY_SDK_SERVER_IP -f devops/indy-pool/Dockerfile -t indy_pool devops/indy-pool/" + bat "docker -H $INDY_SDK_SERVER_IP run -d --network host --name indy_pool -p 9701-9708:9701-9708 indy_pool" + } + + stage('Testing'){ + dir('libsovtoken') { + echo "Libsovtoken Testing: Build" + withEnv([ + "OPENSSL_DIR=$WORKSPACE\\prebuilt", + "SODIUM_LIB_DIR=$WORKSPACE\\prebuilt\\lib", + "LIBINDY_DIR=$WORKSPACE\\indy\\lib", + "PATH=$WORKSPACE\\prebuilt\\lib;$WORKSPACE\\indy\\lib;$PATH", + "RUST_BACKTRACE=1" + ]) { + bat "cargo build" + bat "cargo test --no-run" + + echo "Libsovtoken Testing: Run tests" + withEnv([ + "RUST_TEST_THREADS=1", + "RUST_LOG=debug", + "TEST_POOL_IP=$INDY_SDK_SERVER_IP" + ]) { + bat "cargo test" + } + } + } + } + } finally { + try { + bat "docker -H $INDY_SDK_SERVER_IP stop indy_pool" + } catch (ignore) { + } + try { + bat "docker -H $INDY_SDK_SERVER_IP rm indy_pool" + } catch (ignore) { + } + cleanWs() + } + } + cleanWs() + } +} + pipelineWrapper({ nodeWrapper(nodeLabels.codeBuild) { List _envBuildSrc = [ @@ -125,6 +196,11 @@ pipelineWrapper({ }]] } + builds.builds('windows', [ + build: windowsOSPipeline, + nodeLabel: "$nodeLabels.windows" + ]) + stage("Build and test") { builds.failFast = false utils.parallel builds diff --git a/devops/windows/win-zip-and-upload.sh b/devops/windows/win-zip-and-upload.sh new file mode 100644 index 000000000..f5405cb33 --- /dev/null +++ b/devops/windows/win-zip-and-upload.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -e +set -x + +if [ "$1" = "--help" ] ; then + echo "Usage: " + return +fi + +version="$1" +key="$2" +type="$3" +number="$4" + +[ -z $version ] && exit 1 +[ -z $key ] && exit 2 +[ -z $type ] && exit 3 +[ -z $number ] && exit 4 + +PACKAGE_NAME="libsovtoken" +TEMP_ARCH_DIR=./${PACKAGE_NAME}-zip + +mkdir ${TEMP_ARCH_DIR} + +cp ./target/release/*.dll ${TEMP_ARCH_DIR}/ + +pushd ${TEMP_ARCH_DIR} + zip -r ${PACKAGE_NAME}_${version}.zip ./* + mv ${PACKAGE_NAME}_${version}.zip .. +popd + +rm -rf ${TEMP_ARCH_DIR} + +cat < Date: Tue, 23 Apr 2019 08:24:46 +0300 Subject: [PATCH 12/33] ST-316: Sovtoken CD pipeline Signed-off-by: artem.ivanov --- devops/aws-codebuild/Jenkinsfile.cd | 65 ++++++----- devops/aws-codebuild/Jenkinsfile.ci | 161 ++++++++++++++------------- devops/windows/win-zip-and-upload.sh | 5 +- 3 files changed, 120 insertions(+), 111 deletions(-) mode change 100644 => 100755 devops/windows/win-zip-and-upload.sh diff --git a/devops/aws-codebuild/Jenkinsfile.cd b/devops/aws-codebuild/Jenkinsfile.cd index 2298d6039..c1fe3a084 100644 --- a/devops/aws-codebuild/Jenkinsfile.cd +++ b/devops/aws-codebuild/Jenkinsfile.cd @@ -15,8 +15,8 @@ String srcVersion gitHubUserCredId = env.GITHUB_BOT_USER ?: 'sovbot-github' sovrinPackagingRepo = env.SOVRIN_PACKAGING_REPO ?: 'https://github.com/sovrin-foundation/sovrin-packaging' sovrinPackagingBranch = env.SOVRIN_PACKAGING_BRANCH ?: 'master' -LIBINDY_STREAM = "stable" -LIBINDY_VERSION = "1.8.2" +LIBINDY_STREAM = "master" +LIBINDY_VERSION = "1.8.2-1064" def downloadPackagingUtils() { git branch: sovrinPackagingBranch, credentialsId: gitHubUserCredId, url: sovrinPackagingRepo @@ -26,8 +26,8 @@ def downloadPackagingUtils() { // TODO set proper labels def nodeLabels = [ codeBuild: env.LIBSOVTOKEN_CODEBUILD_NODE_LABEL ?: 'codebuild', - macos: env.LIBSOVTOKEN_MACOS_NODE_LABEL ?: 'macos', - windows: env.LIBSOVTOKEN_WINDOWS_NODE_LABEL ?: 'win2016', + macos : env.LIBSOVTOKEN_MACOS_NODE_LABEL ?: 'macos', + windows : env.LIBSOVTOKEN_WINDOWS_NODE_LABEL ?: 'win2016', ] def codeBuildPipelines = { @@ -163,11 +163,11 @@ def codeBuildPipelines = { stage('Set release parameters') { logger.info("Finding Release version") // def releaseVersion = env.BRANCH_NAME == 'stable' ? '' : "${lastRevision ? lastRevision[0] + 1: 1}.$BUILD_NUMBER" - def releaseVersion = env.BRANCH_NAME == 'stable' ? '' : "$BUILD_NUMBER" + def releaseVersion = env.BRANCH_NAME == 'stable' ? '' : "$BUILD_NUMBER" logger.info("Release version for sovrin repo: $releaseVersion") // debPVersion = utils.packageVersion('deb', srcVersion, releaseVersion, env.BRANCH_NAME == 'master') - debPVersion = env.BRANCH_NAME == 'stable' ? "$srcVersion": "$srcVersion~$releaseVersion" + debPVersion = env.BRANCH_NAME == 'stable' ? "$srcVersion" : "$srcVersion~$releaseVersion" logger.info("Package version for sovrin repo: $debPVersion") // TODO crate and rpm @@ -256,11 +256,11 @@ def codeBuildPipelines = { } Map builds = [ - xenial: xenialBuild, - android: [ - build: androidBuild, - nodeLabel: "$nodeLabels.codeBuild" - ] + xenial : xenialBuild, + android: [ + build : androidBuild, + nodeLabel: "$nodeLabels.codeBuild" + ] ] builds.failFast = false @@ -280,21 +280,21 @@ def macOSPipeline = { echo "===================== Checks for XCode and Rust environment ========================" INSTALLED_XCODE_VERSION = sh(script: '''xcodebuild -version | head -1 | cut -d' ' -f2''', returnStdout: true) echo "INSTALLED_XCODE_VERSION = ${INSTALLED_XCODE_VERSION} and xcodeMinVersion = ${xcodeMinVersion}" - if ( INSTALLED_XCODE_VERSION <= xcodeMinVersion ) { + if (INSTALLED_XCODE_VERSION <= xcodeMinVersion) { msg = "The XCode version must be greater or equal ${xcodeMinVersion}" echo "${msg}" error(msg) } RUST_HOME_EXIST = sh(script: "test -d ${RUST_PATH} && echo '1' || echo '0' ", returnStdout: true).trim() - if ( RUST_HOME_EXIST == '0' ) { + if (RUST_HOME_EXIST == '0') { msg = "Rust home dir does not exist. Make sure that rust is installed in the ${RUST_PATH}." echo "${msg}" error(msg) } RUSTC_VERSION = sh(script: "${RUST_PATH}/rustc --version || echo '0' ", returnStdout: true).trim() - if ( RUSTC_VERSION == '0' ) { + if (RUSTC_VERSION == '0') { msg = "rustc does not exist. Make sure that rust is installed in the ${RUST_PATH}." echo "${msg}" error(msg) @@ -366,13 +366,14 @@ def windowsOSPipeline = { checkout scm } - stage('Setup dependencies'){ + stage('Setup dependencies') { setupRust() bat 'wget -O prebuilt.zip "https://repo.sovrin.org/windows/libindy/deps/indy-sdk-deps.zip"' bat 'unzip prebuilt.zip -d prebuilt' - bat "wget -O indy.zip \"https://repo.sovrin.org/windows/libindy/$LIBINDY_STREAM/$LIBINDY_VERSION/libindy_${LIBINDY_VERSION}.zip\"" + String mainVersion = LIBINDY_VERSION.split('-').first() + bat "wget -O indy.zip \"https://repo.sovrin.org/windows/libindy/$LIBINDY_STREAM/$LIBINDY_VERSION/libindy_${mainVersion}.zip\"" bat 'unzip indy.zip -d indy' } @@ -381,7 +382,7 @@ def windowsOSPipeline = { bat "docker -H $INDY_SDK_SERVER_IP run -d --network host --name indy_pool -p 9701-9708:9701-9708 indy_pool" } - stage('Testing'){ + stage('Testing') { dir('libsovtoken') { echo "Libsovtoken Testing: Build" withEnv([ @@ -404,7 +405,7 @@ def windowsOSPipeline = { } } - stash includes: 'target/release/*.dll', name: 'windowsArtifact' + stash includes: 'target/release/*.dll,target/release/*.dll.lib', name: 'windowsArtifact' } } } finally { @@ -425,6 +426,16 @@ def windowsOSPipeline = { def windowsUpload = { stage('Upload libsovtoken package to Sovrin repo') { + + if (!srcVersion) { + stage('Resolve current source version') { + srcVersion = utils.srcVersion(projectType: 'rust') + logger.info("Current source version: $srcVersion") + } + } + + sh 'chmod -R 777 devops/windows' + unstash name: "windowsArtifact" withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'repo_key')]) { @@ -443,15 +454,15 @@ pipelineWrapper({ Map builds = [ codeBuild: [ - build: codeBuildPipelines, + build : codeBuildPipelines, nodeLabel: "$nodeLabels.codeBuild" ], - macos: [ - build: macOSPipeline, + macos : [ + build : macOSPipeline, nodeLabel: "$nodeLabels.macos" ], - windows: [ - build: windowsOSPipeline, + windows : [ + build : windowsOSPipeline, nodeLabel: "$nodeLabels.windows" ] ] @@ -462,17 +473,17 @@ pipelineWrapper({ } Map publish = [ - macosPublish: [ - build: macosUpload, + macosPublish : [ + build : macosUpload, nodeLabel: "$nodeLabels.codeBuild" ], windowsPublish: [ - build: windowsUpload, + build : windowsUpload, nodeLabel: "$nodeLabels.codeBuild" ] ] - stage ('Publish') { + stage('Publish') { utils.parallel publish } }, { err -> diff --git a/devops/aws-codebuild/Jenkinsfile.ci b/devops/aws-codebuild/Jenkinsfile.ci index c485b4715..fa620cfd6 100644 --- a/devops/aws-codebuild/Jenkinsfile.ci +++ b/devops/aws-codebuild/Jenkinsfile.ci @@ -1,14 +1,14 @@ #!groovy def sovLibrary = library(identifier: 'sovrin-aws-codebuild@master', retriever: modernSCM( - github(credentialsId: 'sovbot-github', repoOwner: 'sovrin-foundation', repository: 'aws-codebuild-pipeline-plugin') + github(credentialsId: 'sovbot-github', repoOwner: 'sovrin-foundation', repository: 'aws-codebuild-pipeline-plugin') )).com.sovrin.pipeline logger = sovLibrary.Logger.new(this) notifier = sovLibrary.Notifier.new(this) logger.setGlobalLevel('TRACE') -LIBINDY_STREAM = "stable" -LIBINDY_VERSION = "1.8.2" +LIBINDY_STREAM = "master" +LIBINDY_VERSION = "1.8.2-1064" def nodeLabels = [ codeBuild: env.LIBSOVTOKEN_CODEBUILD_NODE_LABEL ?: 'codebuild', @@ -16,10 +16,6 @@ def nodeLabels = [ windows: env.LIBSOVTOKEN_WINDOWS_NODE_LABEL ?: 'win2016', ] -def setupRust() { - shell("rustup default 1.32.0") -} - def windowsOSPipeline = { stage("Windows Testing") { def ws_path = "workspace/${env.JOB_NAME}".replace(' ', '_') @@ -35,7 +31,8 @@ def windowsOSPipeline = { bat 'wget -O prebuilt.zip "https://repo.sovrin.org/windows/libindy/deps/indy-sdk-deps.zip"' bat 'unzip prebuilt.zip -d prebuilt' - bat "wget -O indy.zip \"https://repo.sovrin.org/windows/libindy/$LIBINDY_STREAM/$LIBINDY_VERSION/libindy_${LIBINDY_VERSION}.zip\"" + String mainVersion = LIBINDY_VERSION.split('-').first() + bat "wget -O indy.zip \"https://repo.sovrin.org/windows/libindy/$LIBINDY_STREAM/$LIBINDY_VERSION/libindy_${mainVersion}.zip\"" bat 'unzip indy.zip -d indy' } @@ -87,14 +84,14 @@ def windowsOSPipeline = { pipelineWrapper({ nodeWrapper(nodeLabels.codeBuild) { List _envBuildSrc = [ - 'devops', - 'libsovtoken/Cargo.toml', - 'libsovtoken/build_scripts/android/libsovtoken/libsovtoken.dependencies.txt', - 'libsovtoken/build_scripts/android/android_settings.txt' + 'devops', + 'libsovtoken/Cargo.toml', + 'libsovtoken/build_scripts/android/libsovtoken/libsovtoken.dependencies.txt', + 'libsovtoken/build_scripts/android/android_settings.txt' ] List osnames = [ - 'xenial', - //'centos7' + 'xenial', + //'centos7' ] List goals = ['test_dry', 'test'] @@ -118,89 +115,89 @@ pipelineWrapper({ Map builds = osnames.collectEntries { osname -> [(osname): [ "nodeLabel": nodeLabels.codeBuild, - "build": { - def buildImageTag - def prTag = "ci-$osname" + "build" : { + def buildImageTag + def prTag = "ci-$osname" - if (osname == 'xenial') { - stage('Download plugin debs') { - // TODO remove that code once repo.corp sovrin.com - // become available from AWS CodeBuild + if (osname == 'xenial') { + stage('Download plugin debs') { + // TODO remove that code once repo.corp sovrin.com + // become available from AWS CodeBuild - // TODO Aptly on repo.copr.sovrin.com removes '+' signs - // from debian packages making versions in filenames - // not accurate (it concatenates them): - // debian package version: + - // debian package name: + // TODO Aptly on repo.copr.sovrin.com removes '+' signs + // from debian packages making versions in filenames + // not accurate (it concatenates them): + // debian package version: + + // debian package name: - def sovtoken_deb_version = "0.9.5" - def sovtokenfees_deb_version = "0.9.5" + def sovtoken_deb_version = "0.9.5" + def sovtokenfees_deb_version = "0.9.5" - sh """ + sh """ cd ./devops/docker/ci/xenial/ wget --no-check-certificate https://repo.sovrin.org/deb/pool/xenial/stable/s/sovtoken/sovtoken_${sovtoken_deb_version}_amd64.deb wget --no-check-certificate https://repo.sovrin.org/deb/pool/xenial/stable/s/sovtokenfees/sovtokenfees_${sovtokenfees_deb_version}_amd64.deb """ - } - } + } + } - stage("$osname: Resolve image tag") { - def _imgVersion = utils.shStdout("OSNAME=$osname make -C devops image_lst_ci_version -s") - buildImageTag = "${_imgVersion}-${osname}-ci" - logger.info("CI docker image tag: $buildImageTag") - } + stage("$osname: Resolve image tag") { + def _imgVersion = utils.shStdout("OSNAME=$osname make -C devops image_lst_ci_version -s") + buildImageTag = "${_imgVersion}-${osname}-ci" + logger.info("CI docker image tag: $buildImageTag") + } - awsCBHelper.build() { - projectTag = prTag - - // env and build spec - imageTag = buildImageTag - buildspec = 'devops/aws-codebuild/buildspec.ci.yml' - envv = [ - [name: 'OSNAME', value: osname], - [name: 'MAKE_GOALS', value: "${goals.join(' ')}"], - [name: 'INDY_POOL_LOG_LEVEL', value: '10'], - [name: 'INDY_POOL_DIRS', value: '/tmp /var/lib/indy/sandbox /var/log/indy/sandbox'], - ] - computeType = 'medium' - - // build spec for env image - envBuildSrc = _envBuildSrc // TODO make more accurate - envBuildAddPaths = ['./devops/docker/ci/xenial/*.deb'] - envBuildCmds = [ - 'export PROJECT_DIR=$PWD', - 'make -C devops image_lst_ci' - ] - envBuildLocalName = "sovrin/libsovtoken:$buildImageTag" - envBuildEnvv = [ - [name: 'OSNAME', value: osname], - [name: 'LST_CI_DOCKER_TAG', value: buildImageTag], - ] - - onArtifacts = { - this.stage("$osname: Archive artifacts") { - // make targets' logs - utils.archiveArtifacts("logs/*.log*") { - truncate = true - allowEmptyArchive = true - truncateFileSuffix = 'trunc.log' - } - // nodes' logs and validators info - utils.archiveArtifacts("logs/pool/*") { - truncate = false - allowEmptyArchive = true + awsCBHelper.build() { + projectTag = prTag + + // env and build spec + imageTag = buildImageTag + buildspec = 'devops/aws-codebuild/buildspec.ci.yml' + envv = [ + [name: 'OSNAME', value: osname], + [name: 'MAKE_GOALS', value: "${goals.join(' ')}"], + [name: 'INDY_POOL_LOG_LEVEL', value: '10'], + [name: 'INDY_POOL_DIRS', value: '/tmp /var/lib/indy/sandbox /var/log/indy/sandbox'], + ] + computeType = 'medium' + + // build spec for env image + envBuildSrc = _envBuildSrc // TODO make more accurate + envBuildAddPaths = ['./devops/docker/ci/xenial/*.deb'] + envBuildCmds = [ + 'export PROJECT_DIR=$PWD', + 'make -C devops image_lst_ci' + ] + envBuildLocalName = "sovrin/libsovtoken:$buildImageTag" + envBuildEnvv = [ + [name: 'OSNAME', value: osname], + [name: 'LST_CI_DOCKER_TAG', value: buildImageTag], + ] + + onArtifacts = { + this.stage("$osname: Archive artifacts") { + // make targets' logs + utils.archiveArtifacts("logs/*.log*") { + truncate = true + allowEmptyArchive = true + truncateFileSuffix = 'trunc.log' + } + // nodes' logs and validators info + utils.archiveArtifacts("logs/pool/*") { + truncate = false + allowEmptyArchive = true + } + } } } - } - } - }]] + }]] } - + builds.builds('windows', [ build: windowsOSPipeline, nodeLabel: "$nodeLabels.windows" ]) - + stage("Build and test") { builds.failFast = false utils.parallel builds @@ -215,3 +212,7 @@ pipelineWrapper({ notifier.email() } }) + +def setupRust() { + shell("rustup default 1.32.0") +} diff --git a/devops/windows/win-zip-and-upload.sh b/devops/windows/win-zip-and-upload.sh old mode 100644 new mode 100755 index f5405cb33..cb8845a0f --- a/devops/windows/win-zip-and-upload.sh +++ b/devops/windows/win-zip-and-upload.sh @@ -24,6 +24,7 @@ TEMP_ARCH_DIR=./${PACKAGE_NAME}-zip mkdir ${TEMP_ARCH_DIR} cp ./target/release/*.dll ${TEMP_ARCH_DIR}/ +cp ./target/release/*.dll.lib ${TEMP_ARCH_DIR}/ pushd ${TEMP_ARCH_DIR} zip -r ${PACKAGE_NAME}_${version}.zip ./* @@ -33,10 +34,6 @@ popd rm -rf ${TEMP_ARCH_DIR} cat < Date: Tue, 23 Apr 2019 08:37:57 +0300 Subject: [PATCH 13/33] ST-316: Corrected folder suffix building Signed-off-by: artem.ivanov --- devops/aws-codebuild/Jenkinsfile.cd | 16 ++++++++++++++-- devops/aws-codebuild/Jenkinsfile.ci | 2 +- devops/windows/win-zip-and-upload.sh | 12 ++++++------ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/devops/aws-codebuild/Jenkinsfile.cd b/devops/aws-codebuild/Jenkinsfile.cd index c1fe3a084..ef4b03440 100644 --- a/devops/aws-codebuild/Jenkinsfile.cd +++ b/devops/aws-codebuild/Jenkinsfile.cd @@ -442,13 +442,25 @@ def windowsUpload = { withEnv([ "SOVRIN_REPO_HOST=$SOVRIN_REPO_HOST", ]) { - sh "devops/windows/win-zip-and-upload.sh $srcVersion '${repo_key}' $env.BRANCH_NAME $env.BUILD_NUMBER" + def suffix = getSuffix() + sh "devops/windows/win-zip-and-upload.sh $srcVersion '${repo_key}' $env.BRANCH_NAME $suffix" } } } } -pipelineWrapper({ +def getSuffix() { + if (env.BRANCH_NAME == 'master') { + return "-$env.BUILD_NUMBER" + } else if (env.BRANCH_NAME == 'stable') { + return "" + } else { + error "Invalid branch ${env.BRANCH_NAME}" + } +} + + + pipelineWrapper({ //put code build containers inside a vpc under our dev account env.USE_VPC_CONFIG = true diff --git a/devops/aws-codebuild/Jenkinsfile.ci b/devops/aws-codebuild/Jenkinsfile.ci index fa620cfd6..3b0a15df2 100644 --- a/devops/aws-codebuild/Jenkinsfile.ci +++ b/devops/aws-codebuild/Jenkinsfile.ci @@ -193,7 +193,7 @@ pipelineWrapper({ }]] } - builds.builds('windows', [ + builds.put('windows', [ build: windowsOSPipeline, nodeLabel: "$nodeLabels.windows" ]) diff --git a/devops/windows/win-zip-and-upload.sh b/devops/windows/win-zip-and-upload.sh index cb8845a0f..e3c7ed38a 100755 --- a/devops/windows/win-zip-and-upload.sh +++ b/devops/windows/win-zip-and-upload.sh @@ -4,19 +4,19 @@ set -e set -x if [ "$1" = "--help" ] ; then - echo "Usage: " + echo "Usage: " return fi version="$1" key="$2" type="$3" -number="$4" +suffix="$4" [ -z $version ] && exit 1 [ -z $key ] && exit 2 [ -z $type ] && exit 3 -[ -z $number ] && exit 4 +[ -z $suffix ] && exit 4 PACKAGE_NAME="libsovtoken" TEMP_ARCH_DIR=./${PACKAGE_NAME}-zip @@ -34,8 +34,8 @@ popd rm -rf ${TEMP_ARCH_DIR} cat < Date: Mon, 29 Apr 2019 11:55:19 +0300 Subject: [PATCH 14/33] ST-549 Fix libsovtoken identifier Signed-off-by: Nikita Khateev --- libsovtoken/src/logic/request.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsovtoken/src/logic/request.rs b/libsovtoken/src/logic/request.rs index e761fd713..07caa59b6 100644 --- a/libsovtoken/src/logic/request.rs +++ b/libsovtoken/src/logic/request.rs @@ -24,7 +24,8 @@ pub struct Request pub operation: T, pub req_id: ReqId, pub protocol_version: ProtocolVersion, - pub identifier: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub identifier : Option, } impl Request @@ -36,7 +37,7 @@ impl Request operation, protocol_version: PROTOCOL_VERSION, req_id, - identifier: identifier.unwrap_or(DEFAULT_LIBSOVTOKEN_DID.to_string()) + identifier }; } From 6ea3bb0a430c9be7857e60dee39ba7fcbde2b24f Mon Sep 17 00:00:00 2001 From: Nikita Khateev Date: Mon, 29 Apr 2019 12:14:51 +0300 Subject: [PATCH 15/33] ST-549 fix tests Signed-off-by: Nikita Khateev --- libsovtoken/src/logic/build_payment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsovtoken/src/logic/build_payment.rs b/libsovtoken/src/logic/build_payment.rs index 8186a1f69..6ff253d26 100644 --- a/libsovtoken/src/logic/build_payment.rs +++ b/libsovtoken/src/logic/build_payment.rs @@ -207,6 +207,6 @@ mod test_handle_signing { .get(0).unwrap().as_object().unwrap() .get("address").unwrap().as_str().unwrap() ); - assert_eq!("7LSfLv2S6K7zMPrgmJDkZoJNhWvWRzpU7qt9uMR5yz8G".to_string(), request.identifier); + assert_eq!(Some("7LSfLv2S6K7zMPrgmJDkZoJNhWvWRzpU7qt9uMR5yz8G".to_string()), request.identifier); } } \ No newline at end of file From e2261f3850135acec20e0e7c5dc8ac36faddc394 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 1 May 2019 10:45:06 +0300 Subject: [PATCH 16/33] Recovered setting extra to XRef payload Signed-off-by: artem.ivanov --- libsovtoken/src/logic/xfer_payload.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsovtoken/src/logic/xfer_payload.rs b/libsovtoken/src/logic/xfer_payload.rs index 5d47ee8ff..08ed8aee3 100644 --- a/libsovtoken/src/logic/xfer_payload.rs +++ b/libsovtoken/src/logic/xfer_payload.rs @@ -195,7 +195,7 @@ trait InputSigner { input: &Input, outputs: &Outputs, txn_digest: &Option, - _extra: &Option, + extra: &Option, cb: Box, String) + Send + Sync>>, ) -> Result<(), ErrorCode> { @@ -207,7 +207,7 @@ trait InputSigner { Some(json!([input])), Some(json!(outputs)), txn_digest.clone().map(|e| json!(e)), - // _extra.map(|e| json!(e)) + extra.clone().map(|e| json!(e)) ].into_iter().filter_map(|e| e).collect(); let message = serialize_signature(json!(vals))?; From bcdabfe5b60bf9dc8495529173fb39acec2d76ba Mon Sep 17 00:00:00 2001 From: Nikita Khateev Date: Tue, 7 May 2019 11:48:41 +0300 Subject: [PATCH 17/33] Update onto new identifier logic Signed-off-by: Nikita Khateev --- devops/indy-pool/Dockerfile | 8 ++++---- libsovtoken/src/api/mod.rs | 6 ++++-- libsovtoken/tests/utils/mint.rs | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/devops/indy-pool/Dockerfile b/devops/indy-pool/Dockerfile index 426d883e6..82f34a10d 100644 --- a/devops/indy-pool/Dockerfile +++ b/devops/indy-pool/Dockerfile @@ -22,13 +22,13 @@ ARG uid=1000 ARG indy_stream=master -ARG indy_plenum_ver=1.6.735 -ARG indy_node_ver=1.6.874 +ARG indy_plenum_ver=1.8.0~dev780 +ARG indy_node_ver=1.8.0~dev920 ARG indy_anoncreds_ver=1.0.32 ARG python3_indy_crypto_ver=0.4.5 ARG indy_crypto_ver=0.4.5 -ARG token_ver=0.9.6~2 -ARG fees_ver=0.9.6~2 +ARG token_ver=0.9.6~18 +ARG fees_ver=0.9.6~18 # Install environment RUN apt-get update -y && apt-get install -y \ diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index 0a5313283..d6e12e632 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -660,11 +660,13 @@ pub extern "C" fn build_get_txn_fees_handler( let did = match opt_res_to_res_opt!(did) { Ok(did) => did, - Err(e) => { return e as i32; } + Err(e) => None }; + let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111"))); + let get_txn_request = GetFeesRequest::new().as_request(did); - info!("Built GET_TXN_FEES request: {:?}", get_txn_request); + print!("Built GET_TXN_FEES request: {:?}", get_txn_request); let request_pointer = match get_txn_request.serialize_to_pointer() { Ok(p) => p, diff --git a/libsovtoken/tests/utils/mint.rs b/libsovtoken/tests/utils/mint.rs index 2cf69171a..2bac40837 100644 --- a/libsovtoken/tests/utils/mint.rs +++ b/libsovtoken/tests/utils/mint.rs @@ -29,7 +29,7 @@ pub fn mint_tokens(cfg: HashMap, pool_handle: i32, wallet_handle: i let mint_req = Request::::multi_sign_request(wallet_handle, &mint_req, trustee_dids.to_vec()).unwrap(); - let result = indy::ledger::sign_and_submit_request(pool_handle, wallet_handle, did, &mint_req).wait().unwrap(); + let result = indy::ledger::submit_request(pool_handle, &mint_req).wait().unwrap(); utils::parse_mint_response::ParseMintResponse::from_json(&result).map_err(|_| ErrorCode::CommonInvalidStructure) } From 1781632ff6799e78b775e83751162ad3ba066174 Mon Sep 17 00:00:00 2001 From: Nikita Khateev Date: Tue, 7 May 2019 11:51:22 +0300 Subject: [PATCH 18/33] Update CI Signed-off-by: Nikita Khateev --- devops/docker/ci/xenial/Dockerfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/devops/docker/ci/xenial/Dockerfile b/devops/docker/ci/xenial/Dockerfile index 0bebb4f64..5cd1d00f2 100644 --- a/devops/docker/ci/xenial/Dockerfile +++ b/devops/docker/ci/xenial/Dockerfile @@ -36,12 +36,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # or python3-rocksdb are not specified here) ENV LIBINDY_CRYPTO_VERSION ${LIBINDY_CRYPTO_VERSION:-0.4.5} ENV PYTHON3_INDY_CRYPTO_VERSION ${PYTHON3_INDY_CRYPTO_VERSION:-0.4.5} -ENV INDY_PLENUM_VERSION ${INDY_PLENUM_VERSION:-1.6.53} +ENV INDY_PLENUM_VERSION ${INDY_PLENUM_VERSION:-1.8.0~dev780} ENV INDY_ANONCREDS_VERSION ${INDY_ANONCREDS_VERSION:-1.0.11} -ENV INDY_NODE_VERSION ${INDY_NODE_VERSION:-1.6.78} -ENV TOKEN_VER ${TOKEN_VER:-0.9.5} -RUN echo "deb https://repo.sovrin.org/sdk/deb xenial stable" >> /etc/apt/sources.list -RUN echo "deb https://repo.sovrin.org/deb xenial stable" >> /etc/apt/sources.list \ +ENV INDY_NODE_VERSION ${INDY_NODE_VERSION:-1.8.0~dev920} +ENV TOKEN_VER ${TOKEN_VER:-0.9.6~18} +RUN echo "deb https://repo.sovrin.org/sdk/deb xenial master" >> /etc/apt/sources.list +RUN echo "deb https://repo.sovrin.org/deb xenial master" >> /etc/apt/sources.list \ && apt-get update && apt-get install -y --no-install-recommends \ libindy-crypto=${LIBINDY_CRYPTO_VERSION} \ python3-indy-crypto=${PYTHON3_INDY_CRYPTO_VERSION} \ @@ -69,4 +69,4 @@ COPY libsovtoken-ci-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/libsovtoken-ci-entrypoint.sh ENTRYPOINT ["libsovtoken-ci-entrypoint.sh"] -ENV LIBSOVTOKEN_CI_ENV_VERSION=0.55.0 +ENV LIBSOVTOKEN_CI_ENV_VERSION=0.56.0 From 8c342748297c800e472c006015bc51916fbf928d Mon Sep 17 00:00:00 2001 From: Nikita Khateev Date: Tue, 7 May 2019 12:04:26 +0300 Subject: [PATCH 19/33] update anoncreds ver Signed-off-by: Nikita Khateev --- devops/docker/ci/xenial/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops/docker/ci/xenial/Dockerfile b/devops/docker/ci/xenial/Dockerfile index 5cd1d00f2..4da427a47 100644 --- a/devops/docker/ci/xenial/Dockerfile +++ b/devops/docker/ci/xenial/Dockerfile @@ -37,7 +37,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ENV LIBINDY_CRYPTO_VERSION ${LIBINDY_CRYPTO_VERSION:-0.4.5} ENV PYTHON3_INDY_CRYPTO_VERSION ${PYTHON3_INDY_CRYPTO_VERSION:-0.4.5} ENV INDY_PLENUM_VERSION ${INDY_PLENUM_VERSION:-1.8.0~dev780} -ENV INDY_ANONCREDS_VERSION ${INDY_ANONCREDS_VERSION:-1.0.11} +ENV INDY_ANONCREDS_VERSION ${INDY_ANONCREDS_VERSION:-1.0.32} ENV INDY_NODE_VERSION ${INDY_NODE_VERSION:-1.8.0~dev920} ENV TOKEN_VER ${TOKEN_VER:-0.9.6~18} RUN echo "deb https://repo.sovrin.org/sdk/deb xenial master" >> /etc/apt/sources.list From 77c3dd79f3231cd0adc9b055c2d2553ba695c52e Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 13 May 2019 15:21:19 +0300 Subject: [PATCH 20/33] ST-560: Support TAA for XFER Signed-off-by: artem.ivanov --- libsovtoken/src/api/mod.rs | 5 +- libsovtoken/src/logic/build_payment.rs | 21 +++++-- libsovtoken/src/logic/request.rs | 10 ++- libsovtoken/src/logic/xfer_payload.rs | 36 ++++++----- libsovtoken/src/utils/mod.rs | 3 +- libsovtoken/src/utils/txn_author_agreement.rs | 34 ++++++++++ .../tests/build_payment_req_handler_test.rs | 63 +++++++++++++++++++ 7 files changed, 147 insertions(+), 25 deletions(-) create mode 100644 libsovtoken/src/utils/txn_author_agreement.rs diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index 0a5313283..46665c317 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -358,7 +358,7 @@ pub extern "C" fn build_payment_req_handler( cb: JsonCallback ) -> i32 { trace!("api::build_payment_req_handler called >> submitter_did (address) {:?}", submitter_did); - let (inputs, outputs, extra, cb) = match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, cb) { + let (inputs, outputs, extra, taa_acceptance, cb) = match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, cb) { Ok(tup) => tup, Err(error_code) => { trace!("api::build_payment_req_handler << result: {:?}", error_code); @@ -371,7 +371,8 @@ pub extern "C" fn build_payment_req_handler( let result = payload.sign_transfer( &CryptoSdk {}, wallet_handle, - Box::new(move |result| build_payment::handle_signing(command_handle, result, cb)) + taa_acceptance.clone(), + Box::new(move |result| build_payment::handle_signing(command_handle, result, taa_acceptance.clone(), cb)) ); let ec = match result { diff --git a/libsovtoken/src/logic/build_payment.rs b/libsovtoken/src/logic/build_payment.rs index 8186a1f69..74c62d2f4 100644 --- a/libsovtoken/src/logic/build_payment.rs +++ b/libsovtoken/src/logic/build_payment.rs @@ -8,12 +8,13 @@ use logic::input::Inputs; use logic::output::Outputs; use logic::xfer_payload::XferPayload; use utils::base58::{IntoBase58, FromBase58}; +use utils::txn_author_agreement::{TaaAcceptance, extract_taa_acceptance_from_extra}; use ErrorCode; use utils::ffi_support::{string_from_char_ptr, c_pointer_from_str}; type BuildPaymentRequestCb = extern fn(ch: i32, err: i32, request_json: *const c_char) -> i32; -type DeserializedArguments = (Inputs, Outputs, Option, BuildPaymentRequestCb); +type DeserializedArguments = (Inputs, Outputs, Option, Option, BuildPaymentRequestCb); pub fn deserialize_inputs( inputs_json: *const c_char, @@ -41,18 +42,22 @@ pub fn deserialize_inputs( debug!("Deserialized output_json >>> {:?}", outputs); let extra = string_from_char_ptr(extra); + debug!("Converted extra pointer to string >>> {:?}", extra); + + let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(extra)?; debug!("Deserialized extra >>> {:?}", extra); trace!("logic::build_payment::deserialize_inputs << inputs: {:?}, outputs: {:?}, extra: {:?}", inputs, outputs, extra); - return Ok((inputs, outputs, extra, cb)); + return Ok((inputs, outputs, extra, taa_acceptance, cb)); } pub fn handle_signing( command_handle: i32, signed_payload: Result, + taa_acceptance: Option, cb: BuildPaymentRequestCb ) { - let (error_code, pointer) = match build_payment_request_pointer(signed_payload) { + let (error_code, pointer) = match build_payment_request_pointer(signed_payload, taa_acceptance) { Ok(request_pointer) => (ErrorCode::Success, request_pointer), Err(ec) => (ec, c_pointer_from_str("")), }; @@ -61,7 +66,8 @@ pub fn handle_signing( } fn build_payment_request_pointer( - signed_payload: Result + signed_payload: Result, + taa_acceptance: Option ) -> Result<*const c_char, ErrorCode> { let signed_payload = signed_payload?; debug!("Signed payload >>> {:?}", signed_payload); @@ -75,8 +81,11 @@ fn build_payment_request_pointer( let identifier = identifier.as_bytes().from_base58_check(); let identifier = identifier.map(|s| s.into_base58()).map_err(|_| ErrorCode::CommonInvalidStructure)?; - let payment_request = PaymentRequest::new(signed_payload) + let mut payment_request = PaymentRequest::new(signed_payload) .as_request(identifier); + + payment_request.set_taa(taa_acceptance); + debug!("payment_request >>> {:?}", payment_request); return payment_request @@ -177,7 +186,7 @@ mod test_handle_signing { fn call_handle_signing(input_payload: Result) -> Result { let (receiver, command_handle, cb) = callbacks::cb_ec_string(); - handle_signing(command_handle, input_payload, cb.unwrap()); + handle_signing(command_handle, input_payload, None,cb.unwrap()); ResultHandler::one(ErrorCode::Success, receiver) } diff --git a/libsovtoken/src/logic/request.rs b/libsovtoken/src/logic/request.rs index e761fd713..2f3ceb518 100644 --- a/libsovtoken/src/logic/request.rs +++ b/libsovtoken/src/logic/request.rs @@ -10,6 +10,7 @@ use {IndyHandle, ErrorCode}; use utils::constants::general::PROTOCOL_VERSION; use utils::ffi_support::{cstring_from_str, c_pointer_from_string}; use utils::json_conversion::JsonSerialize; +use utils::txn_author_agreement::TaaAcceptance; use utils::random::rand_req_id; use logic::indy_sdk_api::ledger; @@ -25,6 +26,8 @@ pub struct Request pub req_id: ReqId, pub protocol_version: ProtocolVersion, pub identifier: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub taa_acceptance: Option } impl Request @@ -36,10 +39,15 @@ impl Request operation, protocol_version: PROTOCOL_VERSION, req_id, - identifier: identifier.unwrap_or(DEFAULT_LIBSOVTOKEN_DID.to_string()) + identifier: identifier.unwrap_or(DEFAULT_LIBSOVTOKEN_DID.to_string()), + taa_acceptance: None, }; } + pub fn set_taa(&mut self, taa_acceptance: Option) { + self.taa_acceptance = taa_acceptance; + } + pub fn serialize_to_cstring(&self) -> Result { return self.serialize_to_string().map_err(map_err_err!()) .map(|string| cstring_from_str(string)); diff --git a/libsovtoken/src/logic/xfer_payload.rs b/libsovtoken/src/logic/xfer_payload.rs index 08ed8aee3..194bc4fe5 100644 --- a/libsovtoken/src/logic/xfer_payload.rs +++ b/libsovtoken/src/logic/xfer_payload.rs @@ -23,6 +23,7 @@ use logic::input::{Input, Inputs}; use logic::output::Outputs; use logic::hash::Hash; use utils::constants::txn_types::{ATTRIB, GET_ATTRIB}; +use utils::txn_author_agreement::TaaAcceptance; /** * Holds `inputs` and `outputs` @@ -80,7 +81,7 @@ impl XferPayload { if self.inputs.len() < 1 { return Err(ErrorCode::CommonInvalidStructure); } - self.sign(crypto_api, wallet_handle, txn_digest, cb) + self.sign(crypto_api, wallet_handle, None,txn_digest, cb) } @@ -93,15 +94,15 @@ impl XferPayload { * [`Input`]: Input * [`Inputs`]: Inputs */ - pub fn sign_transfer(self, crypto_api: &'static A, wallet_handle: IndyHandle, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { + pub fn sign_transfer(self, crypto_api: &'static A, wallet_handle: IndyHandle, taa_acceptance: Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { trace!("logic::xfer_payload::xfer_payload::sign >> wallet_handle: {:?}", wallet_handle); if self.outputs.len() < 1 || self.inputs.len() < 1 { return Err(ErrorCode::CommonInvalidStructure); } - self.sign(crypto_api, wallet_handle, &None, cb) + self.sign(crypto_api, wallet_handle, taa_acceptance, &None, cb) } - fn sign(mut self, crypto_api: &'static A, wallet_handle: IndyHandle, txn_digest: &Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { + fn sign(mut self, crypto_api: &'static A, wallet_handle: IndyHandle, taa_acceptance: Option, txn_digest: &Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { for output in &mut self.outputs { output.recipient = address::unqualified_address_from_address(&output.recipient)?; } @@ -113,7 +114,7 @@ impl XferPayload { debug!("Indicator stripped from inputs"); - XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), Box::new(move |signatures| { + XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), &taa_acceptance, Box::new(move |signatures| { match signatures { Ok(signatures) => { let payload = Self::clone_payload_add_signatures(&self, signatures); @@ -150,7 +151,7 @@ impl XferPayload { } trait InputSigner { - fn sign_inputs(crypto_api: &'static A, wallet_handle: IndyHandle, inputs: &Inputs, outputs: &Outputs, txn_digest: &Option, extra: &Option, cb: Box, ErrorCode>) + Send + Sync>) + fn sign_inputs(crypto_api: &'static A, wallet_handle: IndyHandle, inputs: &Inputs, outputs: &Outputs, txn_digest: &Option, extra: &Option, taa_acceptance: &Option, cb: Box, ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { let inputs_result: Arc>> = Default::default(); @@ -171,7 +172,7 @@ trait InputSigner { for input in inputs { let cb = cb.clone(); - match Self::sign_input(crypto_api, wallet_handle, input, outputs, txn_digest, extra, Box::new(cb)) { + match Self::sign_input(crypto_api, wallet_handle, input, outputs, txn_digest, extra, taa_acceptance, Box::new(cb)) { err @ Err(_) => { return err; } _ => () } @@ -195,19 +196,22 @@ trait InputSigner { input: &Input, outputs: &Outputs, txn_digest: &Option, - extra: &Option, + _extra: &Option, + taa_acceptance: &Option, cb: Box, String) + Send + Sync>>, ) -> Result<(), ErrorCode> { trace!("logic::xfer_payload::input_signer::sign_input >> input: {:?}, outputs: {:?}, wallet_handle {:?}", input, outputs, wallet_handle); let verkey = address::verkey_from_unqualified_address(&input.address.clone())?; + debug!("Received verkey for payment address >>> {:?}", verkey); let vals: Vec = vec![ Some(json!([input])), Some(json!(outputs)), txn_digest.clone().map(|e| json!(e)), - extra.clone().map(|e| json!(e)) + // extra.clone().map(|e| json!(e)), + taa_acceptance.clone().map(|e| json!(e)) ].into_iter().filter_map(|e| e).collect(); let message = serialize_signature(json!(vals))?; @@ -347,6 +351,7 @@ mod test_xfer_payload { input, outputs, &None, + &None, extra, Box::new(Arc::new(cb)) )?; @@ -359,7 +364,7 @@ mod test_xfer_payload { let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, + XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, &None, Box::new(cb))?; receiver.recv().unwrap().map(|map| map.values().cloned().collect()) } @@ -411,7 +416,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = payload.sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = payload.sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -425,7 +430,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -438,7 +443,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -451,7 +456,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -518,7 +523,7 @@ mod test_xfer_payload { let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap(); + XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap(); let signed_payload = receiver.recv().unwrap().unwrap(); assert_eq!(expected_inputs, signed_payload.inputs); @@ -552,6 +557,7 @@ mod test_xfer_payload { payload.clone().sign_transfer( &CryptoApiHandler {}, wallet_handle, + None, Box::new(cb) ).unwrap(); } diff --git a/libsovtoken/src/utils/mod.rs b/libsovtoken/src/utils/mod.rs index 8a23847ef..1cea16cc5 100644 --- a/libsovtoken/src/utils/mod.rs +++ b/libsovtoken/src/utils/mod.rs @@ -24,4 +24,5 @@ pub mod random; pub mod sequence; pub mod results; #[cfg(any(test, feature = "integration"))] -pub mod test; \ No newline at end of file +pub mod test; +pub mod txn_author_agreement; \ No newline at end of file diff --git a/libsovtoken/src/utils/txn_author_agreement.rs b/libsovtoken/src/utils/txn_author_agreement.rs new file mode 100644 index 000000000..411a10cd7 --- /dev/null +++ b/libsovtoken/src/utils/txn_author_agreement.rs @@ -0,0 +1,34 @@ +use serde_json; +use ErrorCode; + +pub type TaaAcceptance = serde_json::Value; + +const META_FIELD_NAME: &str = "taaAcceptance"; + +pub fn extract_taa_acceptance_from_extra(extra: Option) -> Result<(Option, Option), ErrorCode> { + match extra { + Some(extra_) => { + let extra = serde_json::from_str(&extra_).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; + + match extra { + Some(serde_json::Value::Object(mut extra)) => { + let meta = extra.remove(META_FIELD_NAME); + let extra_json = + if extra.is_empty() { + None + } else { + Some(serde_json::to_string(&extra).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?) + }; + let meta = meta.map(|meta_| json!({META_FIELD_NAME: meta_})); + Ok((extra_json, meta)) + } + Some(extra) => { + let extra_json = serde_json::to_string(&extra).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; + Ok((Some(extra_json), None)) + } + None => Ok((None, None)) + } + } + None => Ok((None, None)) + } +} \ No newline at end of file diff --git a/libsovtoken/tests/build_payment_req_handler_test.rs b/libsovtoken/tests/build_payment_req_handler_test.rs index 434cbd6f9..f67e4e37c 100644 --- a/libsovtoken/tests/build_payment_req_handler_test.rs +++ b/libsovtoken/tests/build_payment_req_handler_test.rs @@ -466,4 +466,67 @@ pub fn build_payment_req_for_not_owned_payment_address() { let err = indy::payments::build_payment_req(wallet_2.handle, Some(dids[0]), &inputs, &outputs, None).wait().unwrap_err(); assert_eq!(err.error_code, ErrorCode::WalletItemNotFound); +} + +#[test] +pub fn build_payment_req_with_taa_acceptance() { + sovtoken::api::sovtoken_init(); + + let did = String::from("Th7MpTaRZVRYnPiabds81Y"); + + let wallet = Wallet::new(); + debug!("wallet id = {:?}", wallet.handle); + + let (payment_addresses, addresses) = generate_payment_addresses(&wallet); + let txo_1 = TXO { address: payment_addresses[0].clone(), seq_no: 1 }.to_libindy_string().unwrap(); + let txo_2 = TXO { address: payment_addresses[1].clone(), seq_no: 1 }.to_libindy_string().unwrap(); + + let inputs = json!([ + txo_1, txo_2 + ]); + + let outputs = json!([ + { + "recipient": payment_addresses[2], + "amount": 10 + }, + { + "recipient": payment_addresses[3], + "amount": 22 + } + ]); + + let expected_operation = json!({ + "type": XFER_PUBLIC, + "inputs": [ + {"address": addresses[0], "seqNo": 1}, + {"address": addresses[1], "seqNo": 1} + ], + "outputs": [ + {"address": addresses[2], "amount": 10}, + {"address": addresses[3], "amount": 22}, + ], + "signatures": [ + "5MLnLHztcHQoGhUsYP9i6PgmwYxwj2dxyY2vhKsztfL8RoYjAyoQYEUqWzsLdqdfLWyVf9KEytAtRaFJh4gLzMJb", + "53scCkcQszJWnxrL7SKcvHyMNL9m4HHYugsNibNVYmxDZLYkanz3QpJtsStDNFjpKCakWC1HVdoMqjrVXPfwACZv" + ] + }); + + let extra = json!({ + "taaAcceptance": { + "mechanism": "acceptance type 1", + "taaDigest": "050e52a57837fff904d3d059c8a123e3a04177042bf467db2b2c27abd8045d5e", + "time": 123456789, + } + }); + + let (req, _) = indy::payments::build_payment_req(wallet.handle, + Some(&did), &inputs.to_string(), &outputs.to_string(), Some(&extra.to_string())).wait().unwrap(); + + let req_parsed: serde_json::Value = serde_json::from_str(&req).unwrap(); + + assert!(req_parsed["taaAcceptance"].as_object().is_some()); + assert_eq!(req_parsed["taaAcceptance"], extra); + + assert_eq!(expected_operation, req_parsed["operation"]); } \ No newline at end of file From 8afc8a3e5bb964db8d1ab9a0985a7389238f35ef Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 13 May 2019 16:09:59 +0300 Subject: [PATCH 21/33] ST-560: refactored support of TAA for XREF Signed-off-by: artem.ivanov --- libsovtoken/src/api/mod.rs | 5 +- .../logic/api_internals/add_request_fees.rs | 18 +++-- libsovtoken/src/logic/build_payment.rs | 36 +++++----- .../src/logic/config/payment_config.rs | 2 +- libsovtoken/src/logic/request.rs | 2 +- libsovtoken/src/logic/xfer_payload.rs | 66 +++++++++---------- libsovtoken/src/utils/txn_author_agreement.rs | 31 +++------ 7 files changed, 75 insertions(+), 85 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index 46665c317..0a5313283 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -358,7 +358,7 @@ pub extern "C" fn build_payment_req_handler( cb: JsonCallback ) -> i32 { trace!("api::build_payment_req_handler called >> submitter_did (address) {:?}", submitter_did); - let (inputs, outputs, extra, taa_acceptance, cb) = match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, cb) { + let (inputs, outputs, extra, cb) = match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, cb) { Ok(tup) => tup, Err(error_code) => { trace!("api::build_payment_req_handler << result: {:?}", error_code); @@ -371,8 +371,7 @@ pub extern "C" fn build_payment_req_handler( let result = payload.sign_transfer( &CryptoSdk {}, wallet_handle, - taa_acceptance.clone(), - Box::new(move |result| build_payment::handle_signing(command_handle, result, taa_acceptance.clone(), cb)) + Box::new(move |result| build_payment::handle_signing(command_handle, result, cb)) ); let ec = match result { diff --git a/libsovtoken/src/logic/api_internals/add_request_fees.rs b/libsovtoken/src/logic/api_internals/add_request_fees.rs index 42e42b36e..7e03d42e6 100644 --- a/libsovtoken/src/logic/api_internals/add_request_fees.rs +++ b/libsovtoken/src/logic/api_internals/add_request_fees.rs @@ -2,7 +2,7 @@ use ErrorCode; use libc::c_char; -use logic::xfer_payload::{XferPayload, serialize_signature}; +use logic::xfer_payload::{XferPayload, Extra, serialize_signature}; use logic::input::Inputs; use logic::output::Outputs; use serde_json; @@ -11,12 +11,13 @@ use logic::indy_sdk_api::crypto_api::CryptoSdk; use utils::constants::txn_types::XFER_PUBLIC; use utils::constants::txn_fields::FEES; use utils::constants::general::JsonCallbackUnwrapped; +use utils::txn_author_agreement::TaaAcceptance; use sha2::{Sha256, Digest}; use hex::ToHex; type SerdeMap = serde_json::Map; type AddRequestFeesCb = extern fn(command_handle_: i32, err: i32, req_with_fees_json: *const c_char) -> i32; -type DeserializedArguments = (Inputs, Outputs, Option, SerdeMap, AddRequestFeesCb); +type DeserializedArguments = (Inputs, Outputs, Option, SerdeMap, AddRequestFeesCb); /** * Deserializes arguments of [`add_request_fees_handler`] @@ -50,6 +51,11 @@ pub fn deserialize_inputs ( let outputs: Outputs = serde_json::from_str(&outputs_json).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; debug!("Deserialized output_json >>> {:?}", outputs); + let extra: Option = if let Some(extra_) = extra { + serde_json::from_str(&extra_).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))? + } else { None }; + debug!("Deserialized extra >>> {:?}", extra); + let request_json_object: serde_json::Value = serde_json::from_str(&request_json).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; trace!("Converted request_json to serde::json::Value"); @@ -87,7 +93,7 @@ pub fn add_fees_to_request_and_serialize( wallet_handle: i32, inputs: Inputs, outputs: Outputs, - extra: Option, + extra: Option, request_json_map: SerdeMap, cb: Box) + Send + Sync> ) -> Result<(), ErrorCode> { @@ -123,7 +129,7 @@ pub fn closure_cb_response(command_handle: i32, cb: JsonCallbackUnwrapped) -> im KEEP all public methods above */ -fn add_fees(wallet_handle: i32, inputs: Inputs, outputs: Outputs, extra: Option, request_json_map: SerdeMap, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { +fn add_fees(wallet_handle: i32, inputs: Inputs, outputs: Outputs, extra: Option, request_json_map: SerdeMap, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { let txn_serialized = serialize_signature(request_json_map.clone().into())?; let mut hasher = Sha256::default(); hasher.input(txn_serialized.as_bytes()); @@ -131,7 +137,7 @@ fn add_fees(wallet_handle: i32, inputs: Inputs, outputs: Outputs, extra: Option< signed_fees(wallet_handle, inputs, outputs, extra, &txn_digest, Box::new(move |fees| { trace!("Added fees to request_json."); match fees { - Ok(fees) => { + Ok((fees, _)) => { let mut map = request_json_map.clone(); map.insert(FEES.to_string(), json!([fees.inputs, fees.outputs, fees.signatures])); cb(Ok(map.clone())); @@ -154,7 +160,7 @@ fn serialize_request_with_fees(request_json_map_with_fees: SerdeMap) -> Result, txn_digest: &Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { +fn signed_fees(wallet_handle: i32, inputs: Inputs, outputs: Outputs, extra: Option, txn_digest: &Option, cb: Box), ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { let fees = XferPayload::new(inputs, outputs, extra); fees.sign_fees(&CryptoSdk{}, wallet_handle, txn_digest, cb)?; Ok(()) diff --git a/libsovtoken/src/logic/build_payment.rs b/libsovtoken/src/logic/build_payment.rs index 74c62d2f4..5900bb95f 100644 --- a/libsovtoken/src/logic/build_payment.rs +++ b/libsovtoken/src/logic/build_payment.rs @@ -6,15 +6,15 @@ use serde_json; use logic::config::payment_config::PaymentRequest; use logic::input::Inputs; use logic::output::Outputs; -use logic::xfer_payload::XferPayload; +use logic::xfer_payload::{XferPayload, Extra}; use utils::base58::{IntoBase58, FromBase58}; -use utils::txn_author_agreement::{TaaAcceptance, extract_taa_acceptance_from_extra}; +use utils::txn_author_agreement::TaaAcceptance; use ErrorCode; use utils::ffi_support::{string_from_char_ptr, c_pointer_from_str}; type BuildPaymentRequestCb = extern fn(ch: i32, err: i32, request_json: *const c_char) -> i32; -type DeserializedArguments = (Inputs, Outputs, Option, Option, BuildPaymentRequestCb); +type DeserializedArguments = (Inputs, Outputs, Option, BuildPaymentRequestCb); pub fn deserialize_inputs( inputs_json: *const c_char, @@ -28,7 +28,7 @@ pub fn deserialize_inputs( let inputs_json = string_from_char_ptr(inputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; debug!("Converted inputs_json pointer to string >>> {:?}", inputs_json); - + let outputs_json = string_from_char_ptr(outputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; debug!("Converted outputs_json pointer to string >>> {:?}", outputs_json); @@ -44,32 +44,32 @@ pub fn deserialize_inputs( let extra = string_from_char_ptr(extra); debug!("Converted extra pointer to string >>> {:?}", extra); - let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(extra)?; + let extra: Option = if let Some(extra_) = extra { + serde_json::from_str(&extra_).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))? + } else { None }; debug!("Deserialized extra >>> {:?}", extra); trace!("logic::build_payment::deserialize_inputs << inputs: {:?}, outputs: {:?}, extra: {:?}", inputs, outputs, extra); - return Ok((inputs, outputs, extra, taa_acceptance, cb)); + return Ok((inputs, outputs, extra, cb)); } pub fn handle_signing( command_handle: i32, - signed_payload: Result, - taa_acceptance: Option, + result: Result<(XferPayload, Option), ErrorCode>, cb: BuildPaymentRequestCb ) { - let (error_code, pointer) = match build_payment_request_pointer(signed_payload, taa_acceptance) { + let (error_code, pointer) = match build_payment_request_pointer(result) { Ok(request_pointer) => (ErrorCode::Success, request_pointer), Err(ec) => (ec, c_pointer_from_str("")), }; - + cb(command_handle, error_code as i32, pointer); } fn build_payment_request_pointer( - signed_payload: Result, - taa_acceptance: Option + result: Result<(XferPayload, Option), ErrorCode>, ) -> Result<*const c_char, ErrorCode> { - let signed_payload = signed_payload?; + let (signed_payload, taa_acceptance) = result?; debug!("Signed payload >>> {:?}", signed_payload); if signed_payload.signatures.is_none() { @@ -84,7 +84,7 @@ fn build_payment_request_pointer( let mut payment_request = PaymentRequest::new(signed_payload) .as_request(identifier); - payment_request.set_taa(taa_acceptance); + payment_request.set_taa_acceptance(taa_acceptance); debug!("payment_request >>> {:?}", payment_request); @@ -184,9 +184,9 @@ mod test_handle_signing { use utils::results::ResultHandler; use utils::test::{default, callbacks}; - fn call_handle_signing(input_payload: Result) -> Result { + fn call_handle_signing(input_payload: Result<(XferPayload, Option), ErrorCode>) -> Result { let (receiver, command_handle, cb) = callbacks::cb_ec_string(); - handle_signing(command_handle, input_payload, None,cb.unwrap()); + handle_signing(command_handle, input_payload, cb.unwrap()); ResultHandler::one(ErrorCode::Success, receiver) } @@ -200,14 +200,14 @@ mod test_handle_signing { #[test] fn test_xfer_without_signatures() { let unsigned_payload = default::xfer_payload_unsigned(); - let result = call_handle_signing(Ok(unsigned_payload)); + let result = call_handle_signing(Ok((unsigned_payload, None))); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } #[test] fn test_signed_xfer_payload() { let signed_payload = default::xfer_payload_signed(); - let result = call_handle_signing(Ok(signed_payload)).unwrap(); + let result = call_handle_signing(Ok((signed_payload, None))).unwrap(); let request: Request = serde_json::from_str(&result).unwrap(); assert_eq!("10001", request.operation.get("type").unwrap()); assert_eq!( diff --git a/libsovtoken/src/logic/config/payment_config.rs b/libsovtoken/src/logic/config/payment_config.rs index 3b764f00d..77912c1ef 100644 --- a/libsovtoken/src/logic/config/payment_config.rs +++ b/libsovtoken/src/logic/config/payment_config.rs @@ -54,7 +54,7 @@ use logic::xfer_payload::XferPayload; [`build_payment_req_handler`]: ../../../api/fn.build_payment_req_handler.html */ -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +#[derive(Serialize, Deserialize, Debug, PartialEq)] pub struct PaymentRequest { #[serde(rename = "type")] txn_type: String, diff --git a/libsovtoken/src/logic/request.rs b/libsovtoken/src/logic/request.rs index 2f3ceb518..9e218aa10 100644 --- a/libsovtoken/src/logic/request.rs +++ b/libsovtoken/src/logic/request.rs @@ -44,7 +44,7 @@ impl Request }; } - pub fn set_taa(&mut self, taa_acceptance: Option) { + pub fn set_taa_acceptance(&mut self, taa_acceptance: Option) { self.taa_acceptance = taa_acceptance; } diff --git a/libsovtoken/src/logic/xfer_payload.rs b/libsovtoken/src/logic/xfer_payload.rs index 194bc4fe5..2a535aecf 100644 --- a/libsovtoken/src/logic/xfer_payload.rs +++ b/libsovtoken/src/logic/xfer_payload.rs @@ -23,7 +23,7 @@ use logic::input::{Input, Inputs}; use logic::output::Outputs; use logic::hash::Hash; use utils::constants::txn_types::{ATTRIB, GET_ATTRIB}; -use utils::txn_author_agreement::TaaAcceptance; +use utils::txn_author_agreement::{TaaAcceptance, extract_taa_acceptance_from_extra}; /** * Holds `inputs` and `outputs` @@ -54,15 +54,17 @@ use utils::txn_author_agreement::TaaAcceptance; * # } * ``` */ -#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)] +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] pub struct XferPayload { pub outputs: Outputs, pub inputs: Inputs, #[serde(skip_serializing_if = "Option::is_none")] - pub extra: Option, + pub extra: Option, pub signatures: Option> } +pub type Extra = serde_json::Value; + unsafe impl Send for XferPayload {} unsafe impl Sync for XferPayload {} @@ -70,18 +72,18 @@ unsafe impl Sync for XferPayload {} impl InputSigner for XferPayload {} impl XferPayload { - pub fn new(inputs: Inputs, outputs: Outputs, extra: Option) -> Self + pub fn new(inputs: Inputs, outputs: Outputs, extra: Option) -> Self { return XferPayload { inputs, outputs, extra, signatures: None }; } // TODO: Add request hash to include while signature - pub fn sign_fees(self, crypto_api: &'static A, wallet_handle: IndyHandle, txn_digest: &Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { + pub fn sign_fees(self, crypto_api: &'static A, wallet_handle: IndyHandle, txn_digest: &Option, cb: Box), ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { trace!("logic::xfer_payload::xfer_payload::sign_fees >> wallet_handle: {:?}", wallet_handle); if self.inputs.len() < 1 { return Err(ErrorCode::CommonInvalidStructure); } - self.sign(crypto_api, wallet_handle, None,txn_digest, cb) + self.sign(crypto_api, wallet_handle, txn_digest, cb) } @@ -94,15 +96,15 @@ impl XferPayload { * [`Input`]: Input * [`Inputs`]: Inputs */ - pub fn sign_transfer(self, crypto_api: &'static A, wallet_handle: IndyHandle, taa_acceptance: Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { + pub fn sign_transfer(self, crypto_api: &'static A, wallet_handle: IndyHandle, cb: Box), ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { trace!("logic::xfer_payload::xfer_payload::sign >> wallet_handle: {:?}", wallet_handle); if self.outputs.len() < 1 || self.inputs.len() < 1 { return Err(ErrorCode::CommonInvalidStructure); } - self.sign(crypto_api, wallet_handle, taa_acceptance, &None, cb) + self.sign(crypto_api, wallet_handle, &None, cb) } - fn sign(mut self, crypto_api: &'static A, wallet_handle: IndyHandle, taa_acceptance: Option, txn_digest: &Option, cb: Box) + Send + Sync>) -> Result<(), ErrorCode> { + fn sign(mut self, crypto_api: &'static A, wallet_handle: IndyHandle, txn_digest: &Option, cb: Box), ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { for output in &mut self.outputs { output.recipient = address::unqualified_address_from_address(&output.recipient)?; } @@ -114,14 +116,14 @@ impl XferPayload { debug!("Indicator stripped from inputs"); - XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), &taa_acceptance, Box::new(move |signatures| { - match signatures { - Ok(signatures) => { - let payload = Self::clone_payload_add_signatures(&self, signatures); + XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), Box::new(move |signatures| { + match (signatures, extract_taa_acceptance_from_extra(self.extra.clone())) { + (Ok(signatures), Ok((extra, taa_acceptance))) => { + let payload = Self::clone_payload_add_signatures(&self, signatures, extra); info!("Built XFER payload: {:?}", payload); - cb(Ok(payload)); + cb(Ok((payload, taa_acceptance))); } - Err(err) => { + (Err(err), _) | (_, Err(err)) => { error!("Got an error while signing utxos: {:?}", err); cb(Err(err)); } @@ -133,7 +135,7 @@ impl XferPayload { res } - fn clone_payload_add_signatures(prev: &Self, signatures: HashMap) -> Self { + fn clone_payload_add_signatures(prev: &Self, signatures: HashMap, extra: Option) -> Self { let signatures = prev.inputs .iter() .map(|input_address| signatures.get(&input_address.to_string())) @@ -144,14 +146,14 @@ impl XferPayload { XferPayload { inputs: prev.inputs.clone(), outputs: prev.outputs.clone(), - extra: prev.extra.clone(), + extra, signatures: Some(signatures), } } } trait InputSigner { - fn sign_inputs(crypto_api: &'static A, wallet_handle: IndyHandle, inputs: &Inputs, outputs: &Outputs, txn_digest: &Option, extra: &Option, taa_acceptance: &Option, cb: Box, ErrorCode>) + Send + Sync>) + fn sign_inputs(crypto_api: &'static A, wallet_handle: IndyHandle, inputs: &Inputs, outputs: &Outputs, txn_digest: &Option, extra: &Option, cb: Box, ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { let inputs_result: Arc>> = Default::default(); @@ -172,7 +174,7 @@ trait InputSigner { for input in inputs { let cb = cb.clone(); - match Self::sign_input(crypto_api, wallet_handle, input, outputs, txn_digest, extra, taa_acceptance, Box::new(cb)) { + match Self::sign_input(crypto_api, wallet_handle, input, outputs, txn_digest, extra, Box::new(cb)) { err @ Err(_) => { return err; } _ => () } @@ -196,8 +198,7 @@ trait InputSigner { input: &Input, outputs: &Outputs, txn_digest: &Option, - _extra: &Option, - taa_acceptance: &Option, + extra: &Option, cb: Box, String) + Send + Sync>>, ) -> Result<(), ErrorCode> { @@ -210,8 +211,7 @@ trait InputSigner { Some(json!([input])), Some(json!(outputs)), txn_digest.clone().map(|e| json!(e)), - // extra.clone().map(|e| json!(e)), - taa_acceptance.clone().map(|e| json!(e)) + extra.clone().map(|e| json!(e)), ].into_iter().filter_map(|e| e).collect(); let message = serialize_signature(json!(vals))?; @@ -338,7 +338,7 @@ mod test_xfer_payload { return (inps, outs); } - fn sign_input_sync(input: &Input, outputs: &Outputs, extra: &Option) -> Result { + fn sign_input_sync(input: &Input, outputs: &Outputs, extra: &Option) -> Result { let wallet_handle = 1; let (sender, receiver) = channel(); let sender = Mutex::new(sender); @@ -351,7 +351,6 @@ mod test_xfer_payload { input, outputs, &None, - &None, extra, Box::new(Arc::new(cb)) )?; @@ -364,7 +363,7 @@ mod test_xfer_payload { let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, &None, + XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, Box::new(cb))?; receiver.recv().unwrap().map(|map| map.values().cloned().collect()) } @@ -416,7 +415,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = payload.sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); + let signed_payload = payload.sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -430,7 +429,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -443,7 +442,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(Vec::new(), outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -456,7 +455,7 @@ mod test_xfer_payload { let (sender, _receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap_err(); + let signed_payload = XferPayload::new(inputs, Vec::new(), None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap_err(); assert_eq!(ErrorCode::CommonInvalidStructure, signed_payload); } @@ -523,8 +522,8 @@ mod test_xfer_payload { let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, None, Box::new(cb)).unwrap(); - let signed_payload = receiver.recv().unwrap().unwrap(); + XferPayload::new(inputs, outputs, None).sign_transfer(&CryptoApiHandler {}, wallet_handle, Box::new(cb)).unwrap(); + let (signed_payload, _) = receiver.recv().unwrap().unwrap(); assert_eq!(expected_inputs, signed_payload.inputs); assert_eq!(expected_outputs, signed_payload.outputs); @@ -557,13 +556,12 @@ mod test_xfer_payload { payload.clone().sign_transfer( &CryptoApiHandler {}, wallet_handle, - None, Box::new(cb) ).unwrap(); } for _ in 0..attempts { - let signed_payload = receiver.recv().unwrap().unwrap(); + let (signed_payload, _) = receiver.recv().unwrap().unwrap(); assert_eq!(expected_signatures, signed_payload.signatures.unwrap()); } } diff --git a/libsovtoken/src/utils/txn_author_agreement.rs b/libsovtoken/src/utils/txn_author_agreement.rs index 411a10cd7..ae322af43 100644 --- a/libsovtoken/src/utils/txn_author_agreement.rs +++ b/libsovtoken/src/utils/txn_author_agreement.rs @@ -5,29 +5,16 @@ pub type TaaAcceptance = serde_json::Value; const META_FIELD_NAME: &str = "taaAcceptance"; -pub fn extract_taa_acceptance_from_extra(extra: Option) -> Result<(Option, Option), ErrorCode> { +pub fn extract_taa_acceptance_from_extra(extra: Option) -> Result<(Option, Option), ErrorCode> { match extra { - Some(extra_) => { - let extra = serde_json::from_str(&extra_).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; - - match extra { - Some(serde_json::Value::Object(mut extra)) => { - let meta = extra.remove(META_FIELD_NAME); - let extra_json = - if extra.is_empty() { - None - } else { - Some(serde_json::to_string(&extra).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?) - }; - let meta = meta.map(|meta_| json!({META_FIELD_NAME: meta_})); - Ok((extra_json, meta)) - } - Some(extra) => { - let extra_json = serde_json::to_string(&extra).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; - Ok((Some(extra_json), None)) - } - None => Ok((None, None)) - } + Some(serde_json::Value::Object(mut extra)) => { + let meta = extra.remove(META_FIELD_NAME); + let extra = if extra.is_empty() { None } else { Some(json!(extra)) }; + let meta = meta.map(|meta_| json!({META_FIELD_NAME: meta_})); + Ok((extra, meta)) + } + Some(extra) => { + Ok((Some(extra), None)) } None => Ok((None, None)) } From c963d80c65edd7b889c4e891e34ccc8a2fe523d7 Mon Sep 17 00:00:00 2001 From: Nikita Khateev Date: Tue, 14 May 2019 12:00:44 +0300 Subject: [PATCH 22/33] Return optional identifier to XFER request builder Signed-off-by: Nikita Khateev --- libsovtoken/src/api/mod.rs | 19 +++--- libsovtoken/src/lib.rs | 3 +- libsovtoken/src/logic/build_payment.rs | 64 +++++++++++++------ .../src/logic/config/get_fees_config.rs | 8 +-- .../src/logic/config/output_mint_config.rs | 4 +- .../src/logic/config/set_fees_config.rs | 6 +- libsovtoken/src/logic/did.rs | 33 +++++----- libsovtoken/src/logic/minting.rs | 8 +-- libsovtoken/src/logic/set_fees.rs | 6 +- libsovtoken/src/logic/verify.rs | 4 +- .../tests/build_payment_req_handler_test.rs | 12 ++-- 11 files changed, 97 insertions(+), 70 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index d6e12e632..a0fe626f5 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -358,20 +358,21 @@ pub extern "C" fn build_payment_req_handler( cb: JsonCallback ) -> i32 { trace!("api::build_payment_req_handler called >> submitter_did (address) {:?}", submitter_did); - let (inputs, outputs, extra, cb) = match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, cb) { - Ok(tup) => tup, - Err(error_code) => { - trace!("api::build_payment_req_handler << result: {:?}", error_code); - return error_code as i32; - } - }; + let (inputs, outputs, extra, submitter_did, cb) = + match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, submitter_did, cb) { + Ok(tup) => tup, + Err(error_code) => { + trace!("api::build_payment_req_handler << result: {:?}", error_code); + return error_code as i32; + } + }; let payload = XferPayload::new(inputs, outputs, extra); let result = payload.sign_transfer( &CryptoSdk {}, wallet_handle, - Box::new(move |result| build_payment::handle_signing(command_handle, result, cb)) + Box::new(move |result| build_payment::handle_signing(command_handle, result, submitter_did.clone(), cb)) ); let ec = match result { @@ -663,7 +664,7 @@ pub extern "C" fn build_get_txn_fees_handler( Err(e) => None }; - let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111"))); + let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111".to_string()))); let get_txn_request = GetFeesRequest::new().as_request(did); print!("Built GET_TXN_FEES request: {:?}", get_txn_request); diff --git a/libsovtoken/src/lib.rs b/libsovtoken/src/lib.rs index 91f2e9c67..c7c80e066 100644 --- a/libsovtoken/src/lib.rs +++ b/libsovtoken/src/lib.rs @@ -33,7 +33,8 @@ extern crate sha2; // ------------------------------------------ extern crate indy_sys; // lib-sdk project -extern crate indyrs as indy; // lib-sdk rust wrapper to get ErrorCodes +extern crate indyrs as indy; +extern crate core; // lib-sdk rust wrapper to get ErrorCodes // ------------------------------------------ // define our crate by defining the modules in the project diff --git a/libsovtoken/src/logic/build_payment.rs b/libsovtoken/src/logic/build_payment.rs index 6ff253d26..fe9bf15be 100644 --- a/libsovtoken/src/logic/build_payment.rs +++ b/libsovtoken/src/logic/build_payment.rs @@ -10,15 +10,17 @@ use logic::xfer_payload::XferPayload; use utils::base58::{IntoBase58, FromBase58}; use ErrorCode; use utils::ffi_support::{string_from_char_ptr, c_pointer_from_str}; +use logic::did::Did; type BuildPaymentRequestCb = extern fn(ch: i32, err: i32, request_json: *const c_char) -> i32; -type DeserializedArguments = (Inputs, Outputs, Option, BuildPaymentRequestCb); +type DeserializedArguments = (Inputs, Outputs, Option, Option, BuildPaymentRequestCb); -pub fn deserialize_inputs( +pub fn deserialize_inputs<'a>( inputs_json: *const c_char, outputs_json: *const c_char, extra: *const c_char, + did: *const c_char, cb: Option ) -> Result { trace!("logic::build_payment::deserialize_inputs >> inputs_json: {:?}, outputs_json: {:?}, extra: {:?}", inputs_json, outputs_json, extra); @@ -27,7 +29,15 @@ pub fn deserialize_inputs( let inputs_json = string_from_char_ptr(inputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; debug!("Converted inputs_json pointer to string >>> {:?}", inputs_json); - + + let did = Did::from_pointer(did).map( + |did| { + did.validate().map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure)) + } + ); + let did = opt_res_to_res_opt!(did)?; + debug!("Converted did pointer to string >>> {:?}", did); + let outputs_json = string_from_char_ptr(outputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; debug!("Converted outputs_json pointer to string >>> {:?}", outputs_json); @@ -44,24 +54,26 @@ pub fn deserialize_inputs( debug!("Deserialized extra >>> {:?}", extra); trace!("logic::build_payment::deserialize_inputs << inputs: {:?}, outputs: {:?}, extra: {:?}", inputs, outputs, extra); - return Ok((inputs, outputs, extra, cb)); + return Ok((inputs, outputs, extra, did, cb)); } pub fn handle_signing( command_handle: i32, signed_payload: Result, + identifier: Option, cb: BuildPaymentRequestCb ) { - let (error_code, pointer) = match build_payment_request_pointer(signed_payload) { + let (error_code, pointer) = match build_payment_request_pointer(signed_payload, identifier) { Ok(request_pointer) => (ErrorCode::Success, request_pointer), Err(ec) => (ec, c_pointer_from_str("")), }; - + cb(command_handle, error_code as i32, pointer); } fn build_payment_request_pointer( - signed_payload: Result + signed_payload: Result, + identifier: Option ) -> Result<*const c_char, ErrorCode> { let signed_payload = signed_payload?; debug!("Signed payload >>> {:?}", signed_payload); @@ -71,9 +83,14 @@ fn build_payment_request_pointer( return Err(ErrorCode::CommonInvalidStructure); } - let identifier = signed_payload.inputs[0].address.clone(); - let identifier = identifier.as_bytes().from_base58_check(); - let identifier = identifier.map(|s| s.into_base58()).map_err(|_| ErrorCode::CommonInvalidStructure)?; + let identifier = match identifier.map(String::from) { + Some(idr) => idr, + None => { + let addr = signed_payload.inputs[0].address.clone(); + let idr = addr.as_bytes().from_base58_check(); + idr.map(|s| s.into_base58()).map_err(|_| ErrorCode::CommonInvalidStructure)? + } + }; let payment_request = PaymentRequest::new(signed_payload) .as_request(identifier); @@ -101,35 +118,44 @@ mod test_deserialize_inputs { deserialize_inputs, }; - pub fn call_deserialize_inputs( + pub fn call_deserialize_inputs<'a>( inputs_json: Option<*const c_char>, outputs_json: Option<*const c_char>, extra: Option<*const c_char>, + did: Option<*const c_char>, cb: Option> ) -> Result { let inputs_json = inputs_json.unwrap_or_else(default::inputs_json_pointer); let outputs_json = outputs_json.unwrap_or_else(default::outputs_json_pointer); let extra = extra.unwrap_or(ptr::null()); + let did = did.unwrap_or_else(default::did); let cb = cb.unwrap_or(Some(default::empty_callback_string)); - return deserialize_inputs(inputs_json, outputs_json, extra, cb); + return deserialize_inputs(inputs_json, outputs_json, extra, did, cb); } #[test] fn deserialize_empty_inputs() { - let result = call_deserialize_inputs(Some(ptr::null()), None, None, None); + let result = call_deserialize_inputs(Some(ptr::null()), None, None, None, None); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } #[test] fn deserialize_empty_outputs() { - let result = call_deserialize_inputs(None, Some(ptr::null()), None, None); + let result = call_deserialize_inputs(None, Some(ptr::null()), None, None, None); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } + #[test] + fn deserialize_empty_did() { + let result = call_deserialize_inputs(None, None, None, Some(ptr::null()), None); + assert!(result.is_ok()); + } + + #[test] fn deserialize_empty_callback() { - let result = call_deserialize_inputs(None, None, None, Some(None)); + let result = call_deserialize_inputs(None, None, None, None, Some(None)); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } @@ -142,7 +168,7 @@ mod test_deserialize_inputs { "seqNo": 2 } }); - let result = call_deserialize_inputs(Some(inputs_json), None, None, None); + let result = call_deserialize_inputs(Some(inputs_json), None, None, None, None); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } @@ -156,13 +182,13 @@ mod test_deserialize_inputs { "seqNo": 5, } }); - let result = call_deserialize_inputs(None, Some(outputs_json), None, None); + let result = call_deserialize_inputs(None, Some(outputs_json), None, None, None); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } #[test] fn deserialize_valid() { - let result = call_deserialize_inputs(None, None, None, None); + let result = call_deserialize_inputs(None, None, None, None, None); assert!(result.is_ok()); } } @@ -177,7 +203,7 @@ mod test_handle_signing { fn call_handle_signing(input_payload: Result) -> Result { let (receiver, command_handle, cb) = callbacks::cb_ec_string(); - handle_signing(command_handle, input_payload, cb.unwrap()); + handle_signing(command_handle, input_payload, None, cb.unwrap()); ResultHandler::one(ErrorCode::Success, receiver) } diff --git a/libsovtoken/src/logic/config/get_fees_config.rs b/libsovtoken/src/logic/config/get_fees_config.rs index dcafe986e..dd0547546 100644 --- a/libsovtoken/src/logic/config/get_fees_config.rs +++ b/libsovtoken/src/logic/config/get_fees_config.rs @@ -16,8 +16,8 @@ use utils::constants::txn_types::GET_FEES; use sovtoken::logic::config::get_fees_config::GetFeesRequest; use sovtoken::logic::did::Did; - let identifier = String::from("hgrhyNXqW4KNTz4wwiV8v"); - let did = Did::new(&identifier).validate().unwrap(); + let identifier = String::from("V4SGRU86Z58d6TV7PBUe6f"); + let did = Did::new(identifier).validate().unwrap(); let get_fees_request = GetFeesRequest::new().as_request(Some(did)); let json_pointer = get_fees_request.serialize_to_pointer().unwrap(); ``` @@ -65,7 +65,7 @@ mod get_fees_config_test { fn initial_get_fee_request() -> Request { let identifier: String = rand_string(21); - let did = Did::new(&identifier); + let did = Did::new(identifier); return GetFeesRequest::new().as_request(Some(did)); } @@ -86,7 +86,7 @@ mod get_fees_config_test { #[test] fn create_request_with_fees_config() { let identifier: String = rand_string(21); - let did = Did::new(&identifier); + let did = Did::new(identifier); let request = GetFeesRequest::new().as_request(Some(did)); assert_eq!(request.operation.txn_type, GET_FEES.to_string()); } diff --git a/libsovtoken/src/logic/config/output_mint_config.rs b/libsovtoken/src/logic/config/output_mint_config.rs index e0bc11123..97e598d2a 100644 --- a/libsovtoken/src/logic/config/output_mint_config.rs +++ b/libsovtoken/src/logic/config/output_mint_config.rs @@ -73,7 +73,7 @@ mod output_mint_config_test { fn initial_mint_request() -> Request { let identifier: String = rand_string(21); - let did = Did::new(&identifier); + let did = Did::new(identifier); let output = Output::new(String::from("E9LNHk8shQ6xe2RfydzXDSsyhWC6vJaUeKE2mmc6mWraDfmKm"), 10); let outputs = vec![output]; return MintRequest::new(outputs, Some(did), None); @@ -96,7 +96,7 @@ mod output_mint_config_test { #[test] fn create_request_with_mint_config() { let identifier: String = rand_string(21); - let did = Did::new(&identifier); + let did = Did::new(identifier); let output = Output::new(String::from("E9LNHk8shQ6xe2RfydzXDSsyhWC6vJaUeKE2mmc6mWraDfmKm"), 10); let outputs = vec![output]; let request = MintRequest::from_config(outputs.clone(), Some(did), None); diff --git a/libsovtoken/src/logic/config/set_fees_config.rs b/libsovtoken/src/logic/config/set_fees_config.rs index fc2a56e55..def25eba9 100644 --- a/libsovtoken/src/logic/config/set_fees_config.rs +++ b/libsovtoken/src/logic/config/set_fees_config.rs @@ -44,7 +44,7 @@ pub type SetFeesMap = HashMap; fees.insert(String::from(txn_types::XFER_PUBLIC), 10); fees.insert(String::from("15"), 3); let identifier = String::from("hgrhyNXqW4KNTz4wwiV8v"); - let did = Did::new(&identifier).validate().unwrap(); + let did = Did::new(identifier).validate().unwrap(); let set_fees = SetFees::new(fees).validate().unwrap(); let set_fees_request = set_fees.as_request(Some(did)); let json_pointer = set_fees_request.serialize_to_pointer().unwrap(); @@ -246,8 +246,8 @@ mod fees_config_test { let hash_map: SetFeesMap = serde_json::from_value(set_fees_json).unwrap(); let set_fees = SetFees::new(hash_map).validate().unwrap(); - let identifier = String::from("hgrhyNXqW4KNTz4wwiV8v"); - let did = Did::new(&identifier).validate().unwrap(); + let identifier = String::from("V4SGRU86Z58d6TV7PBUe6f"); + let did = Did::new(identifier).validate().unwrap(); let request = set_fees.as_request(Some(did)); let fees_from_request = serde_json::to_value(&request.operation.fees).unwrap(); assert_eq!(expected, fees_from_request) diff --git a/libsovtoken/src/logic/did.rs b/libsovtoken/src/logic/did.rs index 65b5b0f35..fb46b6ed7 100644 --- a/libsovtoken/src/logic/did.rs +++ b/libsovtoken/src/logic/did.rs @@ -29,17 +29,17 @@ pub enum DidError { The did needs to be between 20 and 21 characters and contain only alphanumeric characters. */ -#[derive(Debug, PartialEq, Eq)] -pub struct Did<'a>(&'a str); +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Did(String); -impl<'a> Did<'a> { +impl Did { - pub fn new(did_string: &'a str) -> Self { + pub fn new(did_string: String) -> Self { return Did(did_string); } pub fn from_pointer(pointer: *const c_char) -> Option { - return str_from_char_ptr(pointer).map(Self::new); + return str_from_char_ptr(pointer).map(|st| st.to_string()).map(Self::new); } /** @@ -54,28 +54,31 @@ impl<'a> Did<'a> { use sovtoken::logic::did::Did; use sovtoken::logic::did::DidError; - let did_invalid = Did::new("123456789[11234567891"); + let did_invalid = Did::new("123456789[11234567891".to_string()); let error = did_invalid.validate().unwrap_err(); assert_eq!(DidError::InvalidChar('['), error); # } ``` */ pub fn validate(self) -> Result { - let Did(did_string) = self; - let res_did = did_string.from_base58().map_err(map_err_err!()); + + let (res_did, len) = { + let did_string = &self.0; + (did_string.from_base58().map_err(map_err_err!()), did_string.len()) + }; match res_did { Ok(ref vec) if vec.len() == 32 || vec.len() == 16 => Ok(self), Ok(ref vec) => Err(DidError::InvalidLength(vec.len())), Err(DecodeError::InvalidCharacter {character: b, index: _}) => Err(DidError::InvalidChar(b as char)), Err(DecodeError::NonAsciiCharacter {index: _}) => Err(DidError::InvalidChar(0 as char)), - Err(_) => Err(DidError::InvalidLength(did_string.len())) + Err(_) => Err(DidError::InvalidLength(len)) } } } -impl<'a> From> for String { - fn from(did: Did<'a>) -> String { +impl From for String { + fn from(did: Did) -> String { return String::from(did.0); } } @@ -109,22 +112,22 @@ mod test_did_validation { #[test] fn did_invalid_length() { - assert_eq!(Err(DidError::InvalidLength(17)), Did::new(&"1123456789abcdef1".as_bytes().into_base58()).validate()); + assert_eq!(Err(DidError::InvalidLength(17)), Did::new("1123456789abcdef1".as_bytes().into_base58()).validate()); } #[test] fn did_invalid_char() { - assert_eq!(Err(DidError::InvalidChar('!')), Did::new("123456789abcd!efghij").validate()); + assert_eq!(Err(DidError::InvalidChar('!')), Did::new("123456789abcd!efghij".to_string()).validate()); } #[test] fn did_valid_length_16() { - assert!(Did::new(&"1123456789abcdef".as_bytes().into_base58()).validate().is_ok()); + assert!(Did::new("1123456789abcdef".as_bytes().into_base58()).validate().is_ok()); } #[test] fn did_valid_length_32() { - assert!(Did::new(&"1123456789abcdef1123456789abcdef".as_bytes().into_base58()).validate().is_ok()); + assert!(Did::new("1123456789abcdef1123456789abcdef".as_bytes().into_base58()).validate().is_ok()); } #[test] diff --git a/libsovtoken/src/logic/minting.rs b/libsovtoken/src/logic/minting.rs index f805a5e45..eeffb2d08 100644 --- a/libsovtoken/src/logic/minting.rs +++ b/libsovtoken/src/logic/minting.rs @@ -8,14 +8,14 @@ use utils::constants::general::{JsonCallback, JsonCallbackUnwrapped}; use utils::ffi_support::{string_from_char_ptr}; use logic::output::Outputs; -type DeserializedArguments<'a> = (Option>, Outputs, Option, JsonCallbackUnwrapped); +type DeserializedArguments = (Option, Outputs, Option, JsonCallbackUnwrapped); pub fn deserialize_inputs<'a>( did: *const c_char, outputs_json: *const c_char, extra: *const c_char, cb: JsonCallback -) -> Result, ErrorCode> { +) -> Result { trace!("logic::minting::deserialize_inputs >> did: {:?}, outputs_json: {:?}, extra: {:?}", did, outputs_json, extra); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; trace!("Unwrapped callback."); @@ -81,7 +81,7 @@ mod test_build_mint_request { outputs_json: Option<*const c_char>, extra: Option<*const c_char>, cb: Option - ) -> Result, ErrorCode> { + ) -> Result { let req_json = did.unwrap_or_else(default::did); let outputs_json = outputs_json.unwrap_or_else(default::outputs_json_pointer); let extra = extra.unwrap_or(null()); @@ -96,7 +96,7 @@ mod test_build_mint_request { Output::new(String::from("pad:sov:E9LNHk8shQ6xe2RfydzXDSsyhWC6vJaUeKE2mmc6mWraDfmKm"), 12) ]; - let did = Did::new(&"en32ansFeZNERIouv2xA"); + let did = Did::new("en32ansFeZNERIouv2xA".to_string()); let result = build_mint_request(Some(did), outputs, None); assert_eq!(ErrorCode::CommonInvalidStructure, result.unwrap_err()); } diff --git a/libsovtoken/src/logic/set_fees.rs b/libsovtoken/src/logic/set_fees.rs index c9036e6cc..b468d095e 100644 --- a/libsovtoken/src/logic/set_fees.rs +++ b/libsovtoken/src/logic/set_fees.rs @@ -29,13 +29,13 @@ fn txn_name_to_code(txn: &str) -> String { } } -type DeserializedArguments<'a> = (Option>, SetFees, JsonCallbackUnwrapped); +type DeserializedArguments = (Option, SetFees, JsonCallbackUnwrapped); pub fn deserialize_inputs<'a>( did: *const c_char, fees_json: *const c_char, cb: JsonCallback -) -> Result, ErrorCode> { +) -> Result { trace!("logic::set_fees::deserialize_inputs >> did: {:?}, fees_json: {:?}", did, fees_json); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; @@ -74,7 +74,7 @@ mod test_deserialize_inputs { did: Option<*const c_char>, set_fees_json: Option<*const c_char>, cb: Option - ) -> Result, ErrorCode> { + ) -> Result { let did_json = did.unwrap_or_else(default::did); let set_fees_json = set_fees_json.unwrap_or_else(default::set_fees_json); let cb = cb.unwrap_or(Some(default::empty_callback_string)); diff --git a/libsovtoken/src/logic/verify.rs b/libsovtoken/src/logic/verify.rs index b207d8489..4f6105abc 100644 --- a/libsovtoken/src/logic/verify.rs +++ b/libsovtoken/src/logic/verify.rs @@ -6,13 +6,13 @@ use utils::constants::general::{JsonCallback, JsonCallbackUnwrapped}; use utils::ffi_support::string_from_char_ptr; use logic::parsers::common::TXO; -type DeserializedArguments<'a> = (Option>, TXO, JsonCallbackUnwrapped); +type DeserializedArguments = (Option, TXO, JsonCallbackUnwrapped); pub fn deserialize<'a>( did: *const c_char, txo: *const c_char, cb: JsonCallback -) -> Result, ErrorCode> { +) -> Result { trace!("logic::verify::deserialize >> did: {:?}, txo: {:?}", did, txo); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; trace!("Unwrapped callback."); diff --git a/libsovtoken/tests/build_payment_req_handler_test.rs b/libsovtoken/tests/build_payment_req_handler_test.rs index 434cbd6f9..719f9b64e 100644 --- a/libsovtoken/tests/build_payment_req_handler_test.rs +++ b/libsovtoken/tests/build_payment_req_handler_test.rs @@ -140,7 +140,7 @@ fn errors_with_no_submitter_did_json() { fn success_signed_request() { sovtoken::api::sovtoken_init(); - let did = String::from("287asdjkh2323kjnbakjs"); + let did = String::from("V4SGRU86Z58d6TV7PBUe6f"); let wallet = Wallet::new(); debug!("wallet id = {:?}", wallet.handle); @@ -187,7 +187,7 @@ fn success_signed_request() { let error_code = sovtoken::api::build_payment_req_handler( command_handle, wallet.handle, - c_pointer_from_string(did), + c_pointer_from_string(did.clone()), c_pointer_from_string(inputs.to_string()), c_pointer_from_string(outputs.to_string()), ptr::null(), @@ -202,9 +202,7 @@ fn success_signed_request() { debug!("Received request {:?}", request); assert_eq!(&expected_operation, request.get("operation").unwrap()); - let ident = bs58::decode(&addresses[0]).with_check(None).into_vec().unwrap(); - let ident = bs58::encode(ident).into_string(); - assert_eq!(&ident, request.get("identifier").unwrap().as_str().unwrap()); + assert_eq!(&did, request.get("identifier").unwrap().as_str().unwrap()); assert!(request.get("reqId").is_some()); } @@ -268,9 +266,7 @@ fn success_signed_request_from_libindy() { debug!("Received request {:?}", request); assert_eq!(&expected_operation, request.get("operation").unwrap()); - let ident = bs58::decode(&addresses[0]).with_check(None).into_vec().unwrap(); - let ident = bs58::encode(ident).into_string(); - assert_eq!(&ident, request.get("identifier").unwrap().as_str().unwrap()); + assert_eq!(&did, request.get("identifier").unwrap().as_str().unwrap()); assert!(request.get("reqId").is_some()); } From 4158dd2e064fb5e42fff86caa089a6778910a1f2 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 14 May 2019 13:11:23 +0300 Subject: [PATCH 23/33] ST-545: Added helper function for setting fee alias for auth rule Signed-off-by: artem.ivanov --- libsovtoken/src/api/mod.rs | 2 +- libsovtoken/tests/add_fees_for_attrib_test.rs | 1 + .../tests/add_fees_for_cred_def_test.rs | 2 + libsovtoken/tests/add_fees_for_nym.rs | 1 + .../tests/add_fees_for_revoke_reg_def.rs | 2 + libsovtoken/tests/add_fees_for_schema_test.rs | 1 + .../tests/build_add_fees_txn_handler_test.rs | 2 + .../tests/build_fees_txn_handler_test.rs | 1 + .../build_get_utxo_request_handler_test.rs | 1 + .../tests/build_mint_txn_handler_test.rs | 2 + .../tests/build_payment_req_handler_test.rs | 1 + libsovtoken/tests/build_verify_req_test.rs | 1 + libsovtoken/tests/create_payment_tests.rs | 1 + libsovtoken/tests/payment_chaos_tests.rs | 1 + libsovtoken/tests/utils/payment/fees.rs | 130 ++++++++++++++++-- 15 files changed, 138 insertions(+), 11 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index d6e12e632..9bfdba66a 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -660,7 +660,7 @@ pub extern "C" fn build_get_txn_fees_handler( let did = match opt_res_to_res_opt!(did) { Ok(did) => did, - Err(e) => None + Err(_e) => None }; let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111"))); diff --git a/libsovtoken/tests/add_fees_for_attrib_test.rs b/libsovtoken/tests/add_fees_for_attrib_test.rs index 3efece2a8..5047c12e2 100644 --- a/libsovtoken/tests/add_fees_for_attrib_test.rs +++ b/libsovtoken/tests/add_fees_for_attrib_test.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate indyrs as indy; extern crate sovtoken; diff --git a/libsovtoken/tests/add_fees_for_cred_def_test.rs b/libsovtoken/tests/add_fees_for_cred_def_test.rs index 0ecaf7e67..6a18d4a72 100644 --- a/libsovtoken/tests/add_fees_for_cred_def_test.rs +++ b/libsovtoken/tests/add_fees_for_cred_def_test.rs @@ -2,6 +2,8 @@ extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate lazy_static; extern crate indyrs as indy; extern crate sovtoken; diff --git a/libsovtoken/tests/add_fees_for_nym.rs b/libsovtoken/tests/add_fees_for_nym.rs index bb9723dab..f2a804cef 100644 --- a/libsovtoken/tests/add_fees_for_nym.rs +++ b/libsovtoken/tests/add_fees_for_nym.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate indyrs as indy; extern crate sovtoken; diff --git a/libsovtoken/tests/add_fees_for_revoke_reg_def.rs b/libsovtoken/tests/add_fees_for_revoke_reg_def.rs index 691836cce..5352b9a5a 100644 --- a/libsovtoken/tests/add_fees_for_revoke_reg_def.rs +++ b/libsovtoken/tests/add_fees_for_revoke_reg_def.rs @@ -2,6 +2,8 @@ extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate lazy_static; extern crate sovtoken; extern crate indyrs as indy; diff --git a/libsovtoken/tests/add_fees_for_schema_test.rs b/libsovtoken/tests/add_fees_for_schema_test.rs index 3aabdd016..1b6b7fb3e 100644 --- a/libsovtoken/tests/add_fees_for_schema_test.rs +++ b/libsovtoken/tests/add_fees_for_schema_test.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate indyrs as indy; extern crate sovtoken; diff --git a/libsovtoken/tests/build_add_fees_txn_handler_test.rs b/libsovtoken/tests/build_add_fees_txn_handler_test.rs index 2cc7fe451..decb8b4c9 100644 --- a/libsovtoken/tests/build_add_fees_txn_handler_test.rs +++ b/libsovtoken/tests/build_add_fees_txn_handler_test.rs @@ -4,6 +4,8 @@ extern crate serde_json; extern crate serde_derive; extern crate sovtoken; extern crate indyrs as indy; +#[macro_use] +extern crate lazy_static; use indy::future::Future; diff --git a/libsovtoken/tests/build_fees_txn_handler_test.rs b/libsovtoken/tests/build_fees_txn_handler_test.rs index e074c8a92..a653ce403 100644 --- a/libsovtoken/tests/build_fees_txn_handler_test.rs +++ b/libsovtoken/tests/build_fees_txn_handler_test.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate libc; extern crate sovtoken; extern crate indyrs as indy; // lib-sdk project diff --git a/libsovtoken/tests/build_get_utxo_request_handler_test.rs b/libsovtoken/tests/build_get_utxo_request_handler_test.rs index d0870330f..2436048a9 100644 --- a/libsovtoken/tests/build_get_utxo_request_handler_test.rs +++ b/libsovtoken/tests/build_get_utxo_request_handler_test.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate sovtoken; extern crate indyrs as indy; diff --git a/libsovtoken/tests/build_mint_txn_handler_test.rs b/libsovtoken/tests/build_mint_txn_handler_test.rs index 326b2a93b..1414f6444 100644 --- a/libsovtoken/tests/build_mint_txn_handler_test.rs +++ b/libsovtoken/tests/build_mint_txn_handler_test.rs @@ -8,6 +8,8 @@ extern crate indyrs as indy; // lib-sdk project extern crate serde_json; #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; use libc::c_char; use std::ptr; diff --git a/libsovtoken/tests/build_payment_req_handler_test.rs b/libsovtoken/tests/build_payment_req_handler_test.rs index 434cbd6f9..170bf3a63 100644 --- a/libsovtoken/tests/build_payment_req_handler_test.rs +++ b/libsovtoken/tests/build_payment_req_handler_test.rs @@ -6,6 +6,7 @@ extern crate bs58; #[macro_use] extern crate log; #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; use std::ptr; use std::ffi::CString; diff --git a/libsovtoken/tests/build_verify_req_test.rs b/libsovtoken/tests/build_verify_req_test.rs index 1dc321413..7744e0c9e 100644 --- a/libsovtoken/tests/build_verify_req_test.rs +++ b/libsovtoken/tests/build_verify_req_test.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate sovtoken; extern crate indyrs as indy; diff --git a/libsovtoken/tests/create_payment_tests.rs b/libsovtoken/tests/create_payment_tests.rs index 8eae8acb2..af794072a 100644 --- a/libsovtoken/tests/create_payment_tests.rs +++ b/libsovtoken/tests/create_payment_tests.rs @@ -9,6 +9,7 @@ extern crate rand; #[macro_use] extern crate log; #[macro_use] extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate lazy_static; extern crate indyrs as indy; // lib-sdk project extern crate sovtoken; diff --git a/libsovtoken/tests/payment_chaos_tests.rs b/libsovtoken/tests/payment_chaos_tests.rs index b3ebf8c4a..7bf931c0e 100644 --- a/libsovtoken/tests/payment_chaos_tests.rs +++ b/libsovtoken/tests/payment_chaos_tests.rs @@ -4,6 +4,7 @@ extern crate indyrs as indy; // lib-sdk project #[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_json; +#[macro_use] extern crate lazy_static; use indy::future::Future; diff --git a/libsovtoken/tests/utils/payment/fees.rs b/libsovtoken/tests/utils/payment/fees.rs index 9befd8471..56efd7a68 100644 --- a/libsovtoken/tests/utils/payment/fees.rs +++ b/libsovtoken/tests/utils/payment/fees.rs @@ -1,26 +1,136 @@ -extern crate indyrs as indy; - +use sovtoken::utils::constants::general::PAYMENT_METHOD_NAME; use sovtoken::logic::config::set_fees_config::SetFees; use sovtoken::logic::request::Request; -use sovtoken::utils::constants::general::PAYMENT_METHOD_NAME; use utils::wallet::Wallet; use indy::future::Future; -pub fn set_fees(pool_handle: i32, wallet_handle: i32, payment_method: &str, fees: &str, dids: &Vec<&str>, submitter_did: Option<&str>) -> String { - let set_fees_req = indy::payments::build_set_txn_fees_req(wallet_handle, submitter_did, payment_method, &fees).wait().unwrap(); +use std::sync::{Once, ONCE_INIT}; +use std::sync::Mutex; +use std::collections::HashMap; +use std::collections::hash_map::Entry; + +lazy_static! { + static ref AUTH_RULES: Mutex>> = Default::default(); +} + +#[derive(Debug)] +struct AuthRule { + action: String, + txn_type: String, + field: String, + old_value: Option, + new_value: Option, + constraint: serde_json::Value +} +pub fn set_fees(pool_handle: i32, wallet_handle: i32, payment_method: &str, fees: &str, dids: &Vec<&str>, submitter_did: Option<&str>) -> String { + let set_fees_req = ::indy::payments::build_set_txn_fees_req(wallet_handle, submitter_did, payment_method, &fees).wait().unwrap(); let set_fees_req = Request::::multi_sign_request(wallet_handle, &set_fees_req, dids.to_vec()).unwrap(); + ::indy::ledger::submit_request(pool_handle, &set_fees_req).wait().unwrap() + +// TODO: uncomment to set immediately +// let fees: HashMap = +// ::serde_json::from_str::>(fees).unwrap() +// .iter_mut() +// .map(|(k, _v)| (k.to_string(), k.to_string())) +// .collect(); +// +// set_auth_rules_fee(pool_handle, wallet_handle, &submitter_did.unwrap(), &json!(fees).to_string()); +} + +// Helper to set fee alias for auth rules +pub fn set_auth_rules_fee(pool_handle: i32, wallet_handle: i32, submitter_did: &str, rules_fee: &str) { + get_ledger_default_auth_rules(pool_handle); - indy::ledger::submit_request(pool_handle, &set_fees_req).wait().unwrap() + let auth_rules = AUTH_RULES.lock().unwrap(); + + let fees: HashMap = ::serde_json::from_str(rules_fee).unwrap(); + + for (txn_, fee_alias) in fees { + let rules = auth_rules.get(&txn_).unwrap(); + + for auth_rule in rules { + let mut constraint = auth_rule.constraint.clone(); + set_constraint_fee(&mut constraint, &fee_alias); + send_auth_rule(pool_handle, wallet_handle, submitter_did, auth_rule, &constraint); + } + } +} + +fn send_auth_rule(pool_handle: i32, wallet_handle: i32, submitter_did: &str, auth_rule: &AuthRule, constraint: &serde_json::Value) { + let auth_rule_request = ::indy::ledger::build_auth_rule_request(submitter_did, + &auth_rule.txn_type, + &auth_rule.action, + &auth_rule.field, + auth_rule.old_value.as_ref().map(String::as_str), + auth_rule.new_value.as_ref().map(String::as_str), + &constraint.to_string(), + ).wait().unwrap(); + let auth_rule_response = ::indy::ledger::sign_and_submit_request(pool_handle, wallet_handle, submitter_did, &auth_rule_request).wait().unwrap(); + let response: serde_json::Value = ::serde_json::from_str(&auth_rule_response).unwrap(); + assert_eq!(response["op"].as_str().unwrap(), "REPLY"); +} + +fn get_ledger_default_auth_rules(pool_handle: i32) { + lazy_static! { + static ref GET_DEFAULT_AUTH_CONSTRAINTS: Once = ONCE_INIT; + + } + + GET_DEFAULT_AUTH_CONSTRAINTS.call_once(|| { + let get_auth_rule_request = ::indy::ledger::build_get_auth_rule_request(None, None, None, None, None, None).wait().unwrap(); + let get_auth_rule_response = ::indy::ledger::submit_request(pool_handle, &get_auth_rule_request).wait().unwrap(); + let mut get_auth_rule_response: serde_json::Value = ::serde_json::from_str(&get_auth_rule_response).unwrap(); + + let constraints = get_auth_rule_response["result"]["data"].as_object_mut().unwrap(); + + for (constraint_id, constraint) in constraints.iter_mut() { + let parts: Vec<&str> = constraint_id.split("--").collect(); + + let txn_type = parts[0].to_string(); + let action = parts[1].to_string(); + let field = parts[2].to_string(); + let old_value = if action == "ADD" { None } else { Some(parts[3].to_string()) }; + let new_value = if parts[4] == "" { None } else { Some(parts[4].to_string()) }; + + let mut map = AUTH_RULES.lock().unwrap(); + + let rule = AuthRule { action, txn_type: txn_type.clone(), field, old_value, new_value, constraint: constraint.clone() }; + + match map.entry(txn_type) { + Entry::Occupied(rules) => { + let &mut ref mut rules = rules.into_mut(); + rules.push(rule); + } + Entry::Vacant(rules) => { + rules.insert(vec![rule]); + } + }; + } + }) +} + +fn set_constraint_fee(constraint: &mut serde_json::Value, fee_alias: &str) { + match constraint["constraint_id"].as_str().unwrap() { + "ROLE" => { + constraint["metadata"]["fees"] = json!(fee_alias); + } + "OR" | "AND" => { + for mut constraint in constraint["auth_constraints"].as_array_mut().unwrap() { + set_constraint_fee(&mut constraint, fee_alias) + } + } + _ => { panic!() } + } } pub fn get_fees(wallet: &Wallet, pool_handle: i32, submitter_did: Option<&str>) -> String { - let get_fees_req = indy::payments::build_get_txn_fees_req( + let get_fees_req = ::indy::payments::build_get_txn_fees_req( wallet.handle, submitter_did, PAYMENT_METHOD_NAME ).wait().unwrap(); - let result = indy::ledger::submit_request(pool_handle, &get_fees_req).wait().unwrap(); - indy::payments::parse_get_txn_fees_response(PAYMENT_METHOD_NAME, &result).wait().unwrap() -} \ No newline at end of file + let result = ::indy::ledger::submit_request(pool_handle, &get_fees_req).wait().unwrap(); + ::indy::payments::parse_get_txn_fees_response(PAYMENT_METHOD_NAME, &result).wait().unwrap() +} From 709cab557e41957562e8af0364125bf1ca180704 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 14 May 2019 13:46:02 +0300 Subject: [PATCH 24/33] ST-545: Calling setting auth rule instantly. Signed-off-by: artem.ivanov --- libsovtoken/tests/utils/payment/fees.rs | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/libsovtoken/tests/utils/payment/fees.rs b/libsovtoken/tests/utils/payment/fees.rs index 56efd7a68..cdfd15102 100644 --- a/libsovtoken/tests/utils/payment/fees.rs +++ b/libsovtoken/tests/utils/payment/fees.rs @@ -24,30 +24,29 @@ struct AuthRule { constraint: serde_json::Value } -pub fn set_fees(pool_handle: i32, wallet_handle: i32, payment_method: &str, fees: &str, dids: &Vec<&str>, submitter_did: Option<&str>) -> String { +pub fn set_fees(pool_handle: i32, wallet_handle: i32, payment_method: &str, fees: &str, dids: &Vec<&str>, submitter_did: Option<&str>) { let set_fees_req = ::indy::payments::build_set_txn_fees_req(wallet_handle, submitter_did, payment_method, &fees).wait().unwrap(); let set_fees_req = Request::::multi_sign_request(wallet_handle, &set_fees_req, dids.to_vec()).unwrap(); - ::indy::ledger::submit_request(pool_handle, &set_fees_req).wait().unwrap() - -// TODO: uncomment to set immediately -// let fees: HashMap = -// ::serde_json::from_str::>(fees).unwrap() -// .iter_mut() -// .map(|(k, _v)| (k.to_string(), k.to_string())) -// .collect(); -// -// set_auth_rules_fee(pool_handle, wallet_handle, &submitter_did.unwrap(), &json!(fees).to_string()); + ::indy::ledger::submit_request(pool_handle, &set_fees_req).wait().unwrap(); + + let txn_fees: HashMap = + ::serde_json::from_str::>(fees).unwrap() + .iter_mut() + .map(|(k, _v)| (k.to_string(), k.to_string())) + .collect(); + + set_auth_rules_fee(pool_handle, wallet_handle, &submitter_did.unwrap(), &json!(txn_fees).to_string()); } // Helper to set fee alias for auth rules -pub fn set_auth_rules_fee(pool_handle: i32, wallet_handle: i32, submitter_did: &str, rules_fee: &str) { +pub fn set_auth_rules_fee(pool_handle: i32, wallet_handle: i32, submitter_did: &str, txn_fees: &str) { get_ledger_default_auth_rules(pool_handle); let auth_rules = AUTH_RULES.lock().unwrap(); - let fees: HashMap = ::serde_json::from_str(rules_fee).unwrap(); + let txn_fees: HashMap = ::serde_json::from_str(txn_fees).unwrap(); - for (txn_, fee_alias) in fees { + for (txn_, fee_alias) in txn_fees { let rules = auth_rules.get(&txn_).unwrap(); for auth_rule in rules { From f0bbf47401c7280ec3f8a27bbaf0da3b5d1bce1b Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 14 May 2019 14:15:52 +0300 Subject: [PATCH 25/33] ST-560: Corrected XFER payload signing Signed-off-by: artem.ivanov --- libsovtoken/src/api/mod.rs | 2 +- libsovtoken/src/logic/xfer_payload.rs | 28 +++--- libsovtoken/src/utils/txn_author_agreement.rs | 66 +++++++++++++- .../tests/build_payment_req_handler_test.rs | 89 +++++++++++++++++-- 4 files changed, 163 insertions(+), 22 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index d6e12e632..9bfdba66a 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -660,7 +660,7 @@ pub extern "C" fn build_get_txn_fees_handler( let did = match opt_res_to_res_opt!(did) { Ok(did) => did, - Err(e) => None + Err(_e) => None }; let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111"))); diff --git a/libsovtoken/src/logic/xfer_payload.rs b/libsovtoken/src/logic/xfer_payload.rs index 2a535aecf..daa4738a3 100644 --- a/libsovtoken/src/logic/xfer_payload.rs +++ b/libsovtoken/src/logic/xfer_payload.rs @@ -116,14 +116,17 @@ impl XferPayload { debug!("Indicator stripped from inputs"); - XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), Box::new(move |signatures| { - match (signatures, extract_taa_acceptance_from_extra(self.extra.clone())) { - (Ok(signatures), Ok((extra, taa_acceptance))) => { - let payload = Self::clone_payload_add_signatures(&self, signatures, extra); + let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(self.extra.clone())?; + self.extra = extra; + + XferPayload::sign_inputs(crypto_api, wallet_handle, &self.inputs.clone(), &self.outputs.clone(), txn_digest, &self.extra.clone(), &taa_acceptance.clone(), Box::new(move |signatures| { + match signatures { + Ok(signatures) => { + let payload = Self::clone_payload_add_signatures(&self, signatures); info!("Built XFER payload: {:?}", payload); - cb(Ok((payload, taa_acceptance))); + cb(Ok((payload, taa_acceptance.clone()))); } - (Err(err), _) | (_, Err(err)) => { + Err(err) => { error!("Got an error while signing utxos: {:?}", err); cb(Err(err)); } @@ -135,7 +138,7 @@ impl XferPayload { res } - fn clone_payload_add_signatures(prev: &Self, signatures: HashMap, extra: Option) -> Self { + fn clone_payload_add_signatures(prev: &Self, signatures: HashMap) -> Self { let signatures = prev.inputs .iter() .map(|input_address| signatures.get(&input_address.to_string())) @@ -146,14 +149,14 @@ impl XferPayload { XferPayload { inputs: prev.inputs.clone(), outputs: prev.outputs.clone(), - extra, + extra: prev.extra.clone(), signatures: Some(signatures), } } } trait InputSigner { - fn sign_inputs(crypto_api: &'static A, wallet_handle: IndyHandle, inputs: &Inputs, outputs: &Outputs, txn_digest: &Option, extra: &Option, cb: Box, ErrorCode>) + Send + Sync>) + fn sign_inputs(crypto_api: &'static A, wallet_handle: IndyHandle, inputs: &Inputs, outputs: &Outputs, txn_digest: &Option, extra: &Option, taa_acceptance: &Option, cb: Box, ErrorCode>) + Send + Sync>) -> Result<(), ErrorCode> { let inputs_result: Arc>> = Default::default(); @@ -174,7 +177,7 @@ trait InputSigner { for input in inputs { let cb = cb.clone(); - match Self::sign_input(crypto_api, wallet_handle, input, outputs, txn_digest, extra, Box::new(cb)) { + match Self::sign_input(crypto_api, wallet_handle, input, outputs, txn_digest, extra, taa_acceptance, Box::new(cb)) { err @ Err(_) => { return err; } _ => () } @@ -199,6 +202,7 @@ trait InputSigner { outputs: &Outputs, txn_digest: &Option, extra: &Option, + taa_acceptance: &Option, cb: Box, String) + Send + Sync>>, ) -> Result<(), ErrorCode> { @@ -212,6 +216,7 @@ trait InputSigner { Some(json!(outputs)), txn_digest.clone().map(|e| json!(e)), extra.clone().map(|e| json!(e)), + taa_acceptance.clone().map(|e| json!(e)), ].into_iter().filter_map(|e| e).collect(); let message = serialize_signature(json!(vals))?; @@ -352,6 +357,7 @@ mod test_xfer_payload { outputs, &None, extra, + &None, Box::new(Arc::new(cb)) )?; let result = receiver.recv().unwrap(); @@ -363,7 +369,7 @@ mod test_xfer_payload { let (sender, receiver) = channel(); let sender = Mutex::new(sender); let cb = move |result| { sender.lock().unwrap().send(result).unwrap(); }; - XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, + XferPayload::sign_inputs(&CryptoApiHandler {}, wallet_handle, inputs, outputs, &None, &None, &None, Box::new(cb))?; receiver.recv().unwrap().map(|map| map.values().cloned().collect()) } diff --git a/libsovtoken/src/utils/txn_author_agreement.rs b/libsovtoken/src/utils/txn_author_agreement.rs index ae322af43..5a80dd1cc 100644 --- a/libsovtoken/src/utils/txn_author_agreement.rs +++ b/libsovtoken/src/utils/txn_author_agreement.rs @@ -10,7 +10,6 @@ pub fn extract_taa_acceptance_from_extra(extra: Option) -> Re Some(serde_json::Value::Object(mut extra)) => { let meta = extra.remove(META_FIELD_NAME); let extra = if extra.is_empty() { None } else { Some(json!(extra)) }; - let meta = meta.map(|meta_| json!({META_FIELD_NAME: meta_})); Ok((extra, meta)) } Some(extra) => { @@ -18,4 +17,69 @@ pub fn extract_taa_acceptance_from_extra(extra: Option) -> Re } None => Ok((None, None)) } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + pub fn extract_taa_acceptance_from_extra_works() { + let taa_acceptance = json!({ + "mechanism": "acceptance type 1", + "taaDigest": "050e52a57837fff904d3d059c8a123e3a04177042bf467db2b2c27abd8045d5e", + "time": 123456789, + }); + + let extra = json!({ + "taaAcceptance": taa_acceptance.clone() + }); + + let expected_taa = taa_acceptance.clone(); + + let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(Some(extra)).unwrap(); + assert_eq!(None, extra); + assert_eq!(expected_taa, taa_acceptance.unwrap()); + } + + #[test] + pub fn extract_taa_acceptance_from_extra_works_for_some_extra_data() { + let taa_acceptance = json!({ + "mechanism": "acceptance type 1", + "taaDigest": "050e52a57837fff904d3d059c8a123e3a04177042bf467db2b2c27abd8045d5e", + "time": 123456789, + }); + + let extra = json!({ + "data": "some data", + "taaAcceptance": taa_acceptance.clone() + }); + + let expected_extra = json!({"data": "some data"}); + let expected_taa = taa_acceptance.clone(); + + let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(Some(extra)).unwrap(); + assert_eq!(expected_extra, extra.unwrap()); + assert_eq!(expected_taa, taa_acceptance.unwrap()); + } + + #[test] + pub fn extract_taa_acceptance_from_extra_works_for_no_taa_acceptance() { + let extra = json!({ + "data": "some data", + }); + + let expected_extra = json!({"data": "some data"}); + + let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(Some(extra)).unwrap(); + assert_eq!(expected_extra, extra.unwrap()); + assert_eq!(None, taa_acceptance); + } + + #[test] + pub fn extract_taa_acceptance_from_extra_works_for_empty() { + let (extra, taa_acceptance) = extract_taa_acceptance_from_extra(None).unwrap(); + assert_eq!(None, extra); + assert_eq!(None, taa_acceptance); + } } \ No newline at end of file diff --git a/libsovtoken/tests/build_payment_req_handler_test.rs b/libsovtoken/tests/build_payment_req_handler_test.rs index f67e4e37c..38d9e3c0a 100644 --- a/libsovtoken/tests/build_payment_req_handler_test.rs +++ b/libsovtoken/tests/build_payment_req_handler_test.rs @@ -496,6 +496,16 @@ pub fn build_payment_req_with_taa_acceptance() { } ]); + let taa_acceptance = json!({ + "mechanism": "acceptance type 1", + "taaDigest": "050e52a57837fff904d3d059c8a123e3a04177042bf467db2b2c27abd8045d5e", + "time": 123456789, + }); + + let extra = json!({ + "taaAcceptance": taa_acceptance.clone() + }); + let expected_operation = json!({ "type": XFER_PUBLIC, "inputs": [ @@ -507,26 +517,87 @@ pub fn build_payment_req_with_taa_acceptance() { {"address": addresses[3], "amount": 22}, ], "signatures": [ - "5MLnLHztcHQoGhUsYP9i6PgmwYxwj2dxyY2vhKsztfL8RoYjAyoQYEUqWzsLdqdfLWyVf9KEytAtRaFJh4gLzMJb", - "53scCkcQszJWnxrL7SKcvHyMNL9m4HHYugsNibNVYmxDZLYkanz3QpJtsStDNFjpKCakWC1HVdoMqjrVXPfwACZv" + "39qpBrMNPsf8MVz8KfnipRjBTGp6zV5pqkdkN36eVXW6F7XFESZwEvpqYDAvmiejSJMhqRJRcigWns2weQ6J9KuA", + "3Q4pVUGPNADdJT273zpHA4hRnGRAsnRG1BBow5UktVxK8ZTKfw9M9FMkHJDv4ERgRqJx1Wtwfd5Rv3QvuMXon8iN" ] }); + let (req, _) = indy::payments::build_payment_req(wallet.handle, + Some(&did), &inputs.to_string(), &outputs.to_string(), Some(&extra.to_string())).wait().unwrap(); + + let req_parsed: serde_json::Value = serde_json::from_str(&req).unwrap(); + + assert!(req_parsed["taaAcceptance"].as_object().is_some()); + assert_eq!(req_parsed["taaAcceptance"], taa_acceptance); + + assert_eq!(expected_operation, req_parsed["operation"]); +} + +#[test] +pub fn build_payment_req_with_taa_acceptance_and_additional_extra() { + sovtoken::api::sovtoken_init(); + + let did = String::from("Th7MpTaRZVRYnPiabds81Y"); + + let wallet = Wallet::new(); + debug!("wallet id = {:?}", wallet.handle); + + let (payment_addresses, addresses) = generate_payment_addresses(&wallet); + let txo_1 = TXO { address: payment_addresses[0].clone(), seq_no: 1 }.to_libindy_string().unwrap(); + let txo_2 = TXO { address: payment_addresses[1].clone(), seq_no: 1 }.to_libindy_string().unwrap(); + + let inputs = json!([ + txo_1, txo_2 + ]); + + let outputs = json!([ + { + "recipient": payment_addresses[2], + "amount": 10 + }, + { + "recipient": payment_addresses[3], + "amount": 22 + } + ]); + + let taa_acceptance = json!({ + "mechanism": "acceptance type 1", + "taaDigest": "050e52a57837fff904d3d059c8a123e3a04177042bf467db2b2c27abd8045d5e", + "time": 123456789, + }); + let extra = json!({ - "taaAcceptance": { - "mechanism": "acceptance type 1", - "taaDigest": "050e52a57837fff904d3d059c8a123e3a04177042bf467db2b2c27abd8045d5e", - "time": 123456789, - } + "data": "some extra data", + "taaAcceptance": taa_acceptance.clone() + }); + + let expected_operation = json!({ + "type": XFER_PUBLIC, + "inputs": [ + {"address": addresses[0], "seqNo": 1}, + {"address": addresses[1], "seqNo": 1} + ], + "outputs": [ + {"address": addresses[2], "amount": 10}, + {"address": addresses[3], "amount": 22}, + ], + "signatures": [ + "4FLEt14msxsfWoLe58ASjxh7M1h7CFwDFE7U3RMgBm6JGVqWYQ4GwMEkXL8G2WqhKF8TG61R7GMmpx3VP5op2uJ6", + "5EGxtU9THegBbQqKXDTv71VBcNRJQNS9N2HWS267dhRSorpQkJHPbnknHfLRxqnZJynVEZ9FpuzDRW4EtAQJDy5r" + ], + "extra": { + "data": "some extra data" + }, }); let (req, _) = indy::payments::build_payment_req(wallet.handle, - Some(&did), &inputs.to_string(), &outputs.to_string(), Some(&extra.to_string())).wait().unwrap(); + Some(&did), &inputs.to_string(), &outputs.to_string(), Some(&extra.to_string())).wait().unwrap(); let req_parsed: serde_json::Value = serde_json::from_str(&req).unwrap(); assert!(req_parsed["taaAcceptance"].as_object().is_some()); - assert_eq!(req_parsed["taaAcceptance"], extra); + assert_eq!(req_parsed["taaAcceptance"], taa_acceptance); assert_eq!(expected_operation, req_parsed["operation"]); } \ No newline at end of file From 5aaf82088c1495d6bcb705726e6c685ac5cf5b8e Mon Sep 17 00:00:00 2001 From: Darko Kulic Date: Tue, 14 May 2019 16:55:16 +0200 Subject: [PATCH 26/33] CM-2251 Introduce secret macro which hides PII information in release mode. Ind debug it is still shown Signed-off-by: Darko Kulic --- libsovtoken/src/api/mod.rs | 8 ++++---- .../logic/api_internals/add_request_fees.rs | 20 +++++++++---------- .../src/logic/api_internals/create_address.rs | 6 +++--- libsovtoken/src/logic/build_payment.rs | 16 +++++++-------- libsovtoken/src/logic/minting.rs | 16 +++++++-------- libsovtoken/src/logic/payments.rs | 4 ++-- libsovtoken/src/logic/set_fees.rs | 2 +- libsovtoken/src/logic/verify.rs | 8 ++++---- libsovtoken/src/logic/xfer_payload.rs | 8 ++++---- libsovtoken/src/utils/ffi_support.rs | 1 - libsovtoken/src/utils/macros.rs | 12 +++++++++++ 11 files changed, 56 insertions(+), 45 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index 9bfdba66a..558259bec 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -189,7 +189,7 @@ pub extern "C" fn add_request_fees_handler( cb: JsonCallback ) -> i32 { - trace!("api::add_request_fees_handler called did (address) >> {:?}", did); + trace!("api::add_request_fees_handler called did (address) >> {:?}", secret!(&did)); let (inputs, outputs, extra, request_json_map, cb) = match add_request_fees::deserialize_inputs(req_json, inputs_json, outputs_json, extra, cb) { Ok(tup) => tup, Err(error_code) => { @@ -357,7 +357,7 @@ pub extern "C" fn build_payment_req_handler( extra: *const c_char, cb: JsonCallback ) -> i32 { - trace!("api::build_payment_req_handler called >> submitter_did (address) {:?}", submitter_did); + trace!("api::build_payment_req_handler called >> submitter_did (address) {:?}", secret!(&submitter_did)); let (inputs, outputs, extra, cb) = match build_payment::deserialize_inputs(inputs_json, outputs_json, extra, cb) { Ok(tup) => tup, Err(error_code) => { @@ -479,7 +479,7 @@ pub extern "C" fn build_get_utxo_request_handler(command_handle: i32, return ErrorCode::CommonInvalidStructure as i32; } }; - debug!("api::build_get_utxo_request_handler >> wallet_handle: {:?}, payment_address: {:?}", wallet_handle, payment_address); + debug!("api::build_get_utxo_request_handler >> wallet_handle: {:?}, payment_address: {:?}", wallet_handle, secret!(&payment_address)); let utxo_request = GetUtxoOperationRequest::new(String::from(payment_address)); @@ -656,7 +656,7 @@ pub extern "C" fn build_get_txn_fees_handler( did.validate().map_err(map_err_trace!()).or(Err(ErrorCode::CommonInvalidStructure)) }); - debug!("api::build_get_txn_fees_handler >> wallet_handle: {:?}, submitter_did: {:?}", wallet_handle, did); + debug!("api::build_get_txn_fees_handler >> wallet_handle: {:?}, submitter_did: {:?}", wallet_handle, secret!(&did)); let did = match opt_res_to_res_opt!(did) { Ok(did) => did, diff --git a/libsovtoken/src/logic/api_internals/add_request_fees.rs b/libsovtoken/src/logic/api_internals/add_request_fees.rs index 7e03d42e6..a4b08c4ca 100644 --- a/libsovtoken/src/logic/api_internals/add_request_fees.rs +++ b/libsovtoken/src/logic/api_internals/add_request_fees.rs @@ -29,32 +29,32 @@ pub fn deserialize_inputs ( extra: *const c_char, cb: Option ) -> Result { - debug!("logic::add_request_fees::deserialize_inputs >> req_json: {:?}, inputs_json: {:?}, outputs_json: {:?}", req_json, inputs_json, outputs_json); + debug!("logic::add_request_fees::deserialize_inputs >> req_json: {:?}, inputs_json: {:?}, outputs_json: {:?}", secret!(&req_json), secret!(&inputs_json), secret!(&outputs_json)); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; let request_json = string_from_char_ptr(req_json).ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; - debug!("Converted request_json pointer into string >>> {:?}", request_json); + debug!("Converted request_json pointer into string >>> {:?}", secret!(&request_json)); let inputs_json = string_from_char_ptr(inputs_json).ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; - debug!("Converted inputs_json pointer to string >>> {:?}", inputs_json); + debug!("Converted inputs_json pointer to string >>> {:?}", secret!(&inputs_json)); let outputs_json = string_from_char_ptr(outputs_json).ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; - debug!("Converted outputs_json pointer to string >>> {:?}", outputs_json); + debug!("Converted outputs_json pointer to string >>> {:?}", secret!(&outputs_json)); let extra = string_from_char_ptr(extra); debug!("Converted extra pointer to string >>> {:?}", extra); let inputs: Inputs = serde_json::from_str(&inputs_json).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; - debug!("Deserialized input_json >>> {:?}", inputs); + debug!("Deserialized input_json >>> {:?}", secret!(&inputs)); let outputs: Outputs = serde_json::from_str(&outputs_json).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; - debug!("Deserialized output_json >>> {:?}", outputs); + debug!("Deserialized output_json >>> {:?}", secret!(&outputs)); let extra: Option = if let Some(extra_) = extra { serde_json::from_str(&extra_).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))? } else { None }; - debug!("Deserialized extra >>> {:?}", extra); + debug!("Deserialized extra >>> {:?}", secret!(&extra)); let request_json_object: serde_json::Value = serde_json::from_str(&request_json).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))?; trace!("Converted request_json to serde::json::Value"); @@ -62,7 +62,7 @@ pub fn deserialize_inputs ( let request_json_map = request_json_object.as_object().ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; trace!("Converted request_json to hash_map"); - debug!("Deserialized values: inputs: {:?}, outputs: {:?}, request_json_map: {:?}", inputs, outputs, request_json_map); + debug!("Deserialized values: inputs: {:?}, outputs: {:?}, request_json_map: {:?}", secret!(&inputs), secret!(&outputs), secret!(&request_json_map)); return Ok(( inputs, outputs, @@ -97,7 +97,7 @@ pub fn add_fees_to_request_and_serialize( request_json_map: SerdeMap, cb: Box) + Send + Sync> ) -> Result<(), ErrorCode> { - trace!("logic::add_request_fees::add_fees_to_request_and_serialize >> wallet_handle: {:?}, inputs: {:?}, outputs: {:?}, request_json_map: {:?}", wallet_handle, inputs, outputs, request_json_map); + trace!("logic::add_request_fees::add_fees_to_request_and_serialize >> wallet_handle: {:?}, inputs: {:?}, outputs: {:?}, request_json_map: {:?}", wallet_handle, secret!(&inputs), secret!(&outputs), secret!(&request_json_map)); let res = add_fees(wallet_handle, inputs, outputs, extra, request_json_map, Box::new(move |request_json_map_updated|{ let rm_fees = request_json_map_updated.map(|request_json_map_with_fees| serialize_request_with_fees(request_json_map_with_fees)); match rm_fees { @@ -152,7 +152,7 @@ fn add_fees(wallet_handle: i32, inputs: Inputs, outputs: Outputs, extra: Option< } fn serialize_request_with_fees(request_json_map_with_fees: SerdeMap) -> Result { - trace!("fee_map: {:?}", request_json_map_with_fees); + trace!("fee_map: {:?}", secret!(&request_json_map_with_fees)); let serialized_request_with_fees = serde_json::to_string(&json!(request_json_map_with_fees)) .or(Err(ErrorCode::CommonInvalidStructure))?; trace!("Serialized request_with_fees"); diff --git a/libsovtoken/src/logic/api_internals/create_address.rs b/libsovtoken/src/logic/api_internals/create_address.rs index e7a4ea8cd..2ba9a4a24 100644 --- a/libsovtoken/src/logic/api_internals/create_address.rs +++ b/libsovtoken/src/logic/api_internals/create_address.rs @@ -29,14 +29,14 @@ pub fn deserialize_arguments( .ok_or(ErrorCode::CommonInvalidStructure) .map_err(map_err_err!())?; - debug!("api::create_payment_address_handler json_config_string >> {:?}", json_config_string); + debug!("api::create_payment_address_handler json_config_string >> {:?}", secret!(&json_config_string)); // TODO: Only continue when seed is missing, not on any error. let config = PaymentAddressConfig::from_json(&json_config_string) .map_err(map_err_trace!()) .unwrap_or(PaymentAddressConfig { seed: "".to_string() }); - debug!("api::create_payment_address_handler PaymentAddressConfig >> {:?}", config); + debug!("api::create_payment_address_handler PaymentAddressConfig >> {:?}", secret!(&config)); Ok((config, cb)) } @@ -52,7 +52,7 @@ pub fn create_address_cb(command_handle: i32, cb: JsonCallbackUnwrapped) -> impl return; } - debug!("create_payment_address_handler returning payment address of '{}'", &payment_address); + debug!("create_payment_address_handler returning payment address of '{}'", secret!(&payment_address)); let payment_address_cstring = cstring_from_str(payment_address); let payment_address_ptr = payment_address_cstring.as_ptr(); diff --git a/libsovtoken/src/logic/build_payment.rs b/libsovtoken/src/logic/build_payment.rs index eeb84771e..25ad8eeb3 100644 --- a/libsovtoken/src/logic/build_payment.rs +++ b/libsovtoken/src/logic/build_payment.rs @@ -22,24 +22,24 @@ pub fn deserialize_inputs( extra: *const c_char, cb: Option ) -> Result { - trace!("logic::build_payment::deserialize_inputs >> inputs_json: {:?}, outputs_json: {:?}, extra: {:?}", inputs_json, outputs_json, extra); + trace!("logic::build_payment::deserialize_inputs >> inputs_json: {:?}, outputs_json: {:?}, extra: {:?}", secret!(&inputs_json), secret!(&outputs_json), secret!(&extra)); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; let inputs_json = string_from_char_ptr(inputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; - debug!("Converted inputs_json pointer to string >>> {:?}", inputs_json); + debug!("Converted inputs_json pointer to string >>> {:?}", secret!(&inputs_json)); let outputs_json = string_from_char_ptr(outputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; - debug!("Converted outputs_json pointer to string >>> {:?}", outputs_json); + debug!("Converted outputs_json pointer to string >>> {:?}", secret!(&outputs_json)); let inputs: Inputs = serde_json::from_str(&inputs_json).map_err(map_err_err!()) .or(Err(ErrorCode::CommonInvalidStructure))?; - debug!("Deserialized input_json >>> {:?}", inputs); + debug!("Deserialized input_json >>> {:?}", secret!(&inputs)); let outputs: Outputs = serde_json::from_str(&outputs_json).map_err(map_err_err!()) .or(Err(ErrorCode::CommonInvalidStructure))?; - debug!("Deserialized output_json >>> {:?}", outputs); + debug!("Deserialized output_json >>> {:?}", secret!(&outputs)); let extra = string_from_char_ptr(extra); debug!("Converted extra pointer to string >>> {:?}", extra); @@ -47,9 +47,9 @@ pub fn deserialize_inputs( let extra: Option = if let Some(extra_) = extra { serde_json::from_str(&extra_).map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure))? } else { None }; - debug!("Deserialized extra >>> {:?}", extra); + debug!("Deserialized extra >>> {:?}", secret!(&extra)); - trace!("logic::build_payment::deserialize_inputs << inputs: {:?}, outputs: {:?}, extra: {:?}", inputs, outputs, extra); + trace!("logic::build_payment::deserialize_inputs << inputs: {:?}, outputs: {:?}, extra: {:?}", secret!(&inputs), secret!(&outputs), secret!(&extra)); return Ok((inputs, outputs, extra, cb)); } @@ -70,7 +70,7 @@ fn build_payment_request_pointer( result: Result<(XferPayload, Option), ErrorCode>, ) -> Result<*const c_char, ErrorCode> { let (signed_payload, taa_acceptance) = result?; - debug!("Signed payload >>> {:?}", signed_payload); + debug!("Signed payload >>> {:?}", secret!(&signed_payload)); if signed_payload.signatures.is_none() { error!("Building an unsigned payment request."); diff --git a/libsovtoken/src/logic/minting.rs b/libsovtoken/src/logic/minting.rs index f805a5e45..8d4527f04 100644 --- a/libsovtoken/src/logic/minting.rs +++ b/libsovtoken/src/logic/minting.rs @@ -16,7 +16,7 @@ pub fn deserialize_inputs<'a>( extra: *const c_char, cb: JsonCallback ) -> Result, ErrorCode> { - trace!("logic::minting::deserialize_inputs >> did: {:?}, outputs_json: {:?}, extra: {:?}", did, outputs_json, extra); + trace!("logic::minting::deserialize_inputs >> did: {:?}, outputs_json: {:?}, extra: {:?}", secret!(&did), secret!(&outputs_json), secret!(&extra)); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; trace!("Unwrapped callback."); @@ -26,20 +26,20 @@ pub fn deserialize_inputs<'a>( } ); let did = opt_res_to_res_opt!(did)?; - debug!("Converted did pointer to string >>> {:?}", did); + debug!("Converted did pointer to string >>> {:?}", secret!(&did)); let outputs_json = string_from_char_ptr(outputs_json) .ok_or(ErrorCode::CommonInvalidStructure)?; - debug!("Converted outputs_json pointer to string >>> {:?}", outputs_json); + debug!("Converted outputs_json pointer to string >>> {:?}", secret!(&outputs_json)); let outputs: Outputs = serde_json::from_str(&outputs_json) .or(Err(ErrorCode::CommonInvalidStructure))?; - debug!("Deserialized output_json >>> {:?}", outputs); + debug!("Deserialized output_json >>> {:?}", secret!(&outputs)); let extra = string_from_char_ptr(extra); - debug!("Deserialized extra >>> {:?}", extra); + debug!("Deserialized extra >>> {:?}", secret!(&extra)); - trace!("logic::minting::deserialize_inputs << did: {:?}, outputs: {:?}, extra: {:?}", did, outputs, extra); + trace!("logic::minting::deserialize_inputs << did: {:?}, outputs: {:?}, extra: {:?}", secret!(&did), secret!(&outputs), secret!(&extra)); return Ok((did, outputs, extra, cb)); } @@ -48,7 +48,7 @@ pub fn build_mint_request( mut outputs: Outputs, extra: Option, ) -> Result<*const c_char, ErrorCode> { - trace!("logic::minting::build_mint_request >> did: {:?}, outputs: {:?}", did, outputs); + trace!("logic::minting::build_mint_request >> did: {:?}, outputs: {:?}", secret!(&did), secret!(&outputs)); for output in &mut outputs { let address = address::unqualified_address_from_address(&output.recipient)?; @@ -57,7 +57,7 @@ pub fn build_mint_request( trace!("Stripped pay:sov: from outputs"); let mint_request = MintRequest::from_config(outputs, did, extra); - info!("Built a mint request >>> {:?}", mint_request); + info!("Built a mint request >>> {:?}", secret!(&mint_request)); let ptr = mint_request.serialize_to_pointer() .or(Err(ErrorCode::CommonInvalidStructure)); diff --git a/libsovtoken/src/logic/payments.rs b/libsovtoken/src/logic/payments.rs index 90c37512a..c0f4a9826 100644 --- a/libsovtoken/src/logic/payments.rs +++ b/libsovtoken/src/logic/payments.rs @@ -35,7 +35,7 @@ impl CreatePaymentHandler { trace!("calling self.injected_api.indy_create_key"); let verkey = self.injected_api.indy_create_key(wallet_id, config)?; - trace!("got verkey from self.injected_api.indy_create_key {}", verkey); + trace!("got verkey from self.injected_api.indy_create_key {}", secret!(&verkey)); return address::qualified_address_from_verkey(&verkey); } @@ -51,7 +51,7 @@ impl CreatePaymentHandler { let cb_closure = move | err: ErrorCode, verkey : String | { let res = if ErrorCode::Success == err { - trace!("got verkey from self.injected_api.indy_create_key_async {}", verkey); + trace!("got verkey from self.injected_api.indy_create_key_async {}", secret!(&verkey)); address::qualified_address_from_verkey(&verkey) } else { Err(err) diff --git a/libsovtoken/src/logic/set_fees.rs b/libsovtoken/src/logic/set_fees.rs index c9036e6cc..66e3e2fb1 100644 --- a/libsovtoken/src/logic/set_fees.rs +++ b/libsovtoken/src/logic/set_fees.rs @@ -36,7 +36,7 @@ pub fn deserialize_inputs<'a>( fees_json: *const c_char, cb: JsonCallback ) -> Result, ErrorCode> { - trace!("logic::set_fees::deserialize_inputs >> did: {:?}, fees_json: {:?}", did, fees_json); + trace!("logic::set_fees::deserialize_inputs >> did: {:?}, fees_json: {:?}", secret!(&did), secret!(&fees_json)); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; let did = Did::from_pointer(did).map(|did| { diff --git a/libsovtoken/src/logic/verify.rs b/libsovtoken/src/logic/verify.rs index b207d8489..fa62099bb 100644 --- a/libsovtoken/src/logic/verify.rs +++ b/libsovtoken/src/logic/verify.rs @@ -13,7 +13,7 @@ pub fn deserialize<'a>( txo: *const c_char, cb: JsonCallback ) -> Result, ErrorCode> { - trace!("logic::verify::deserialize >> did: {:?}, txo: {:?}", did, txo); + trace!("logic::verify::deserialize >> did: {:?}, txo: {:?}", secret!(&did), secret!(&txo)); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; trace!("Unwrapped callback."); @@ -26,18 +26,18 @@ pub fn deserialize<'a>( }) )?; - debug!("Converted did pointer to string >>> {:?}", did); + debug!("Converted did pointer to string >>> {:?}", secret!(&did)); let txo = string_from_char_ptr(txo) .ok_or(ErrorCode::CommonInvalidStructure)?; - debug!("Converted txo pointer to string >>> {:?}", txo); + debug!("Converted txo pointer to string >>> {:?}", secret!(&txo)); let txo = TXO::from_libindy_string(&txo) .map_err(map_err_err!()) .map_err(|_| ErrorCode::CommonInvalidStructure)?; debug!("Deserialized txo: {:?}", txo); - trace!("logic::verify::deserialize << did: {:?}, txo: {:?}", did, txo); + trace!("logic::verify::deserialize << did: {:?}, txo: {:?}", secret!(&did), secret!(&txo)); Ok((did, txo, cb)) } diff --git a/libsovtoken/src/logic/xfer_payload.rs b/libsovtoken/src/logic/xfer_payload.rs index daa4738a3..52011fef3 100644 --- a/libsovtoken/src/logic/xfer_payload.rs +++ b/libsovtoken/src/logic/xfer_payload.rs @@ -206,10 +206,10 @@ trait InputSigner { cb: Box, String) + Send + Sync>>, ) -> Result<(), ErrorCode> { - trace!("logic::xfer_payload::input_signer::sign_input >> input: {:?}, outputs: {:?}, wallet_handle {:?}", input, outputs, wallet_handle); + trace!("logic::xfer_payload::input_signer::sign_input >> input: {:?}, outputs: {:?}, wallet_handle {:?}", secret!(&input), secret!(&outputs), wallet_handle); let verkey = address::verkey_from_unqualified_address(&input.address.clone())?; - debug!("Received verkey for payment address >>> {:?}", verkey); + debug!("Received verkey for payment address >>> {:?}", secret!(&verkey)); let vals: Vec = vec![ Some(json!([input])), @@ -221,13 +221,13 @@ trait InputSigner { let message = serialize_signature(json!(vals))?; - debug!("Message to sign >>> {:?}", &message); + debug!("Message to sign >>> {:?}", secret!(&message)); let input_key = input.to_string(); let ca = move |signature: Result| { let key = input_key.clone(); - debug!("Received encoded signature >>> {:?} for input {:?}", signature, key); + debug!("Received encoded signature >>> {:?} for input {:?}", secret!(&signature), secret!(&key)); cb(signature, key); }; diff --git a/libsovtoken/src/utils/ffi_support.rs b/libsovtoken/src/utils/ffi_support.rs index 56c4294e9..00c16bd89 100644 --- a/libsovtoken/src/utils/ffi_support.rs +++ b/libsovtoken/src/utils/ffi_support.rs @@ -56,7 +56,6 @@ pub fn c_pointer_from_string(string: String) -> *const c_char { */ pub fn deserialize_from_char_ptr<'a, S: JsonDeserialize<'a>>(str_ptr: *const c_char) -> Result { let json_string = str_from_char_ptr(str_ptr).ok_or(ErrorCode::CommonInvalidStructure)?; - println!("deserializing = {:?}",json_string); let result = S::from_json(json_string).map_err(|_| ErrorCode::CommonInvalidStructure); return result; diff --git a/libsovtoken/src/utils/macros.rs b/libsovtoken/src/utils/macros.rs index 690be8a9e..b95d850ab 100644 --- a/libsovtoken/src/utils/macros.rs +++ b/libsovtoken/src/utils/macros.rs @@ -52,3 +52,15 @@ macro_rules! rust_slice { unsafe { slice::from_raw_parts($x, $y as usize) } } } + +#[cfg(debug_assertions)] +#[macro_export] +macro_rules! secret { + ($val:expr) => {{ $val }}; +} + +#[cfg(not(debug_assertions))] +#[macro_export] +macro_rules! secret { + ($val:expr) => {{ "_" }}; +} \ No newline at end of file From 61c514af6be5f7b8f6c5e5b71474c9e05ce40734 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Wed, 15 May 2019 14:52:57 +0300 Subject: [PATCH 27/33] ST-545: Sending auth rules in a parallel Signed-off-by: artem.ivanov --- libsovtoken/src/api/mod.rs | 1 - .../tests/build_fees_txn_handler_test.rs | 6 +-- libsovtoken/tests/utils/payment/fees.rs | 43 ++++++++++++------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index 9bfdba66a..7ecf3e7ed 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -666,7 +666,6 @@ pub extern "C" fn build_get_txn_fees_handler( let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111"))); let get_txn_request = GetFeesRequest::new().as_request(did); - print!("Built GET_TXN_FEES request: {:?}", get_txn_request); let request_pointer = match get_txn_request.serialize_to_pointer() { Ok(p) => p, diff --git a/libsovtoken/tests/build_fees_txn_handler_test.rs b/libsovtoken/tests/build_fees_txn_handler_test.rs index a653ce403..a3b3461c3 100644 --- a/libsovtoken/tests/build_fees_txn_handler_test.rs +++ b/libsovtoken/tests/build_fees_txn_handler_test.rs @@ -142,10 +142,8 @@ pub fn build_and_submit_set_fees() { }).to_string(); fees::set_fees(pool_handle, wallet.handle, &payment_method, &fees, &dids, Some(dids[0])); - } - #[test] pub fn build_and_submit_set_fees_with_names() { let payment_method = sovtoken::utils::constants::general::PAYMENT_METHOD_NAME; @@ -200,7 +198,7 @@ pub fn build_and_submit_set_fees_with_empty_did() { "ATTRIB": 2 }).to_string(); - fees::set_fees(pool_handle, wallet.handle, &payment_method, &fees, &dids, None); + fees::set_fees(pool_handle, wallet.handle, &payment_method, &fees, &dids, Some(dids[0])); let current_fees = fees::get_fees(&wallet, pool_handle, None); let current_fees_value: serde_json::Value = serde_json::from_str(¤t_fees).unwrap(); @@ -212,6 +210,6 @@ pub fn build_and_submit_set_fees_with_empty_did() { "ATTRIB": 0 }).to_string(); - fees::set_fees(pool_handle, wallet.handle, &payment_method, &fees, &dids, None); + fees::set_fees(pool_handle, wallet.handle, &payment_method, &fees, &dids, Some(dids[0])); } \ No newline at end of file diff --git a/libsovtoken/tests/utils/payment/fees.rs b/libsovtoken/tests/utils/payment/fees.rs index cdfd15102..7ca661123 100644 --- a/libsovtoken/tests/utils/payment/fees.rs +++ b/libsovtoken/tests/utils/payment/fees.rs @@ -40,24 +40,32 @@ pub fn set_fees(pool_handle: i32, wallet_handle: i32, payment_method: &str, fees // Helper to set fee alias for auth rules pub fn set_auth_rules_fee(pool_handle: i32, wallet_handle: i32, submitter_did: &str, txn_fees: &str) { - get_ledger_default_auth_rules(pool_handle); + _get_default_ledger_auth_rules(pool_handle); let auth_rules = AUTH_RULES.lock().unwrap(); - let txn_fees: HashMap = ::serde_json::from_str(txn_fees).unwrap(); + let fees: HashMap = ::serde_json::from_str(txn_fees).unwrap(); - for (txn_, fee_alias) in txn_fees { - let rules = auth_rules.get(&txn_).unwrap(); + let mut responses: Vec>> = Vec::new(); - for auth_rule in rules { - let mut constraint = auth_rule.constraint.clone(); - set_constraint_fee(&mut constraint, &fee_alias); - send_auth_rule(pool_handle, wallet_handle, submitter_did, auth_rule, &constraint); + for (txn_, fee_alias) in fees { + if let Some(rules) = auth_rules.get(&txn_) { + for auth_rule in rules { + let mut constraint = auth_rule.constraint.clone(); + _set_fee_to_constraint(&mut constraint, &fee_alias); + responses.push(_send_auth_rule(pool_handle, wallet_handle, submitter_did, auth_rule, &constraint)); + } } } + + let _response = responses + .into_iter() + .map(|response| _check_auth_rule_responses(response)) + .collect::>(); } -fn send_auth_rule(pool_handle: i32, wallet_handle: i32, submitter_did: &str, auth_rule: &AuthRule, constraint: &serde_json::Value) { +fn _send_auth_rule(pool_handle: i32, wallet_handle: i32, submitter_did: &str, + auth_rule: &AuthRule, constraint: &serde_json::Value) -> Box> { let auth_rule_request = ::indy::ledger::build_auth_rule_request(submitter_did, &auth_rule.txn_type, &auth_rule.action, @@ -66,12 +74,17 @@ fn send_auth_rule(pool_handle: i32, wallet_handle: i32, submitter_did: &str, aut auth_rule.new_value.as_ref().map(String::as_str), &constraint.to_string(), ).wait().unwrap(); - let auth_rule_response = ::indy::ledger::sign_and_submit_request(pool_handle, wallet_handle, submitter_did, &auth_rule_request).wait().unwrap(); - let response: serde_json::Value = ::serde_json::from_str(&auth_rule_response).unwrap(); - assert_eq!(response["op"].as_str().unwrap(), "REPLY"); + + ::indy::ledger::sign_and_submit_request(pool_handle, wallet_handle, submitter_did, &auth_rule_request) +} + +fn _check_auth_rule_responses(response: Box>) { + let response = response.wait().unwrap(); + let response: serde_json::Value = ::serde_json::from_str(&response).unwrap(); + assert_eq!("REPLY", response["op"].as_str().unwrap()); } -fn get_ledger_default_auth_rules(pool_handle: i32) { +fn _get_default_ledger_auth_rules(pool_handle: i32) { lazy_static! { static ref GET_DEFAULT_AUTH_CONSTRAINTS: Once = ONCE_INIT; @@ -110,14 +123,14 @@ fn get_ledger_default_auth_rules(pool_handle: i32) { }) } -fn set_constraint_fee(constraint: &mut serde_json::Value, fee_alias: &str) { +fn _set_fee_to_constraint(constraint: &mut serde_json::Value, fee_alias: &str) { match constraint["constraint_id"].as_str().unwrap() { "ROLE" => { constraint["metadata"]["fees"] = json!(fee_alias); } "OR" | "AND" => { for mut constraint in constraint["auth_constraints"].as_array_mut().unwrap() { - set_constraint_fee(&mut constraint, fee_alias) + _set_fee_to_constraint(&mut constraint, fee_alias) } } _ => { panic!() } From 541e45bcd20d28c9531d8c608c8603c8c86ba7f4 Mon Sep 17 00:00:00 2001 From: Nikita Khateev Date: Thu, 16 May 2019 15:55:55 +0300 Subject: [PATCH 28/33] Fix MC Signed-off-by: Nikita Khateev --- libsovtoken/src/logic/build_payment.rs | 13 ++-- libsovtoken/src/logic/minting.rs | 6 +- libsovtoken/src/logic/set_fees.rs | 4 +- libsovtoken/src/logic/verify.rs | 4 +- .../tests/build_payment_req_handler_test.rs | 65 +++++++++++++++++++ 5 files changed, 76 insertions(+), 16 deletions(-) diff --git a/libsovtoken/src/logic/build_payment.rs b/libsovtoken/src/logic/build_payment.rs index 462182221..5a795d921 100644 --- a/libsovtoken/src/logic/build_payment.rs +++ b/libsovtoken/src/logic/build_payment.rs @@ -31,13 +31,10 @@ pub fn deserialize_inputs( .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; debug!("Converted inputs_json pointer to string >>> {:?}", secret!(&inputs_json)); - let did = Did::from_pointer(did).map( - |did| { - did.validate().map_err(map_err_err!()).or(Err(ErrorCode::CommonInvalidStructure)) - } - ); - let did = opt_res_to_res_opt!(did)?; - debug!("Converted did pointer to string >>> {:?}", did); + let did = if let Some(did) = Did::from_pointer(did) { + Some(did.validate().map_err(map_err_err!()).map_err(|_| ErrorCode::CommonInvalidStructure)?) + } else {None}; + debug!("Converted did pointer to string >>> {:?}", secret!(&did)); let outputs_json = string_from_char_ptr(outputs_json) .ok_or(ErrorCode::CommonInvalidStructure).map_err(map_err_err!())?; @@ -127,7 +124,7 @@ mod test_deserialize_inputs { deserialize_inputs, }; - pub fn call_deserialize_inputs<'a>( + pub fn call_deserialize_inputs( inputs_json: Option<*const c_char>, outputs_json: Option<*const c_char>, extra: Option<*const c_char>, diff --git a/libsovtoken/src/logic/minting.rs b/libsovtoken/src/logic/minting.rs index 0656c1763..5e4741823 100644 --- a/libsovtoken/src/logic/minting.rs +++ b/libsovtoken/src/logic/minting.rs @@ -10,12 +10,12 @@ use logic::output::Outputs; type DeserializedArguments = (Option, Outputs, Option, JsonCallbackUnwrapped); -pub fn deserialize_inputs<'a>( +pub fn deserialize_inputs( did: *const c_char, outputs_json: *const c_char, extra: *const c_char, cb: JsonCallback -) -> Result, ErrorCode> { +) -> Result { trace!("logic::minting::deserialize_inputs >> did: {:?}, outputs_json: {:?}, extra: {:?}", secret!(&did), secret!(&outputs_json), secret!(&extra)); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; trace!("Unwrapped callback."); @@ -76,7 +76,7 @@ mod test_build_mint_request { use utils::ffi_support::{c_pointer_from_str}; use utils::test::default; - pub fn call_deserialize_inputs<'a>( + pub fn call_deserialize_inputs( did: Option<*const c_char>, outputs_json: Option<*const c_char>, extra: Option<*const c_char>, diff --git a/libsovtoken/src/logic/set_fees.rs b/libsovtoken/src/logic/set_fees.rs index 686ae00b7..7798a14c5 100644 --- a/libsovtoken/src/logic/set_fees.rs +++ b/libsovtoken/src/logic/set_fees.rs @@ -31,7 +31,7 @@ fn txn_name_to_code(txn: &str) -> String { type DeserializedArguments = (Option, SetFees, JsonCallbackUnwrapped); -pub fn deserialize_inputs<'a>( +pub fn deserialize_inputs( did: *const c_char, fees_json: *const c_char, cb: JsonCallback @@ -70,7 +70,7 @@ mod test_deserialize_inputs { use utils::test::default; use utils::ffi_support::{c_pointer_from_str}; - pub fn call_deserialize_inputs<'a>( + pub fn call_deserialize_inputs( did: Option<*const c_char>, set_fees_json: Option<*const c_char>, cb: Option diff --git a/libsovtoken/src/logic/verify.rs b/libsovtoken/src/logic/verify.rs index 1d4e824b2..732715181 100644 --- a/libsovtoken/src/logic/verify.rs +++ b/libsovtoken/src/logic/verify.rs @@ -8,14 +8,12 @@ use logic::parsers::common::TXO; type DeserializedArguments = (Option, TXO, JsonCallbackUnwrapped); -pub fn deserialize<'a>( +pub fn deserialize( did: *const c_char, txo: *const c_char, cb: JsonCallback ) -> Result { trace!("logic::verify::deserialize >> did: {:?}, txo: {:?}", secret!(&did), secret!(&txo)); -) -> Result { - trace!("logic::verify::deserialize >> did: {:?}, txo: {:?}", did, txo); let cb = cb.ok_or(ErrorCode::CommonInvalidStructure)?; trace!("Unwrapped callback."); diff --git a/libsovtoken/tests/build_payment_req_handler_test.rs b/libsovtoken/tests/build_payment_req_handler_test.rs index 621ce4363..aa1f5cac6 100644 --- a/libsovtoken/tests/build_payment_req_handler_test.rs +++ b/libsovtoken/tests/build_payment_req_handler_test.rs @@ -271,6 +271,71 @@ fn success_signed_request_from_libindy() { } +#[test] // TODO: look carefully on changes +fn success_signed_request_from_libindy_no_identifier() { + + sovtoken::api::sovtoken_init(); + + let wallet = Wallet::new(); + debug!("wallet id = {:?}", wallet.handle); + + let (payment_addresses, addresses) = generate_payment_addresses(&wallet); + + let txo_1 = TXO { address: payment_addresses[0].clone(), seq_no: 1 }.to_libindy_string().unwrap(); + let txo_2 = TXO { address: payment_addresses[1].clone(), seq_no: 1 }.to_libindy_string().unwrap(); + + let inputs = json!([ + txo_1, txo_2 + ]); + + let outputs = json!([ + { + "recipient": payment_addresses[2], + "amount": 10 + }, + { + "recipient": payment_addresses[3], + "amount": 22 + } + ]); + + let expected_operation = json!({ + "type": XFER_PUBLIC, + "inputs": [ + {"address": addresses[0], "seqNo": 1}, + {"address": addresses[1], "seqNo": 1}, + ], + "outputs": [ + {"address": addresses[2], "amount": 10}, + {"address": addresses[3], "amount": 22}, + ], + "signatures": [ + "bnuZUPAq5jgpqvaQBzXKBQ973yCpjL1pkqJjiBtVPybpzzKGnPv3uE3VufBVZtR6hq2y55b8MSJpPFVMqskBy3m", + "4HpwuknWrSpJCs2qXEMZA1kbAsP9WxJFaoHq1cH7W3yxLg5R2fHV8QPdY5Hz2bgDmGkRitLaPa3HbF65kTxNpNTe" + ] + }); + + trace!("Calling build_payment_req"); + + let (request_string, _) = indy::payments::build_payment_req( + wallet.handle, + None, + &inputs.to_string(), + &outputs.to_string(), + None, + ).wait().unwrap(); + + let request: serde_json::value::Value = serde_json::from_str(&request_string).unwrap(); + debug!("Received request {:?}", request); + + assert_eq!(&expected_operation, request.get("operation").unwrap()); + let ident = bs58::decode(&addresses[0]).with_check(None).into_vec().unwrap(); + let ident = bs58::encode(ident).into_string(); + assert_eq!(&ident, request.get("identifier").unwrap().as_str().unwrap()); + assert!(request.get("reqId").is_some()); + +} + #[test] pub fn build_and_submit_payment_req() { let wallet = Wallet::new(); From 6df8775ade9b7388b356f7640b2b3b0b6544d39b Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Fri, 17 May 2019 17:12:04 +0300 Subject: [PATCH 29/33] ST-545: Updated Indy-Node version Signed-off-by: artem.ivanov --- devops/indy-pool/Dockerfile | 8 ++++---- libsovtoken/tests/utils/payment/fees.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/devops/indy-pool/Dockerfile b/devops/indy-pool/Dockerfile index 82f34a10d..094b3909a 100644 --- a/devops/indy-pool/Dockerfile +++ b/devops/indy-pool/Dockerfile @@ -22,13 +22,13 @@ ARG uid=1000 ARG indy_stream=master -ARG indy_plenum_ver=1.8.0~dev780 -ARG indy_node_ver=1.8.0~dev920 +ARG indy_plenum_ver=1.8.0~dev791 +ARG indy_node_ver=1.8.0~dev932 ARG indy_anoncreds_ver=1.0.32 ARG python3_indy_crypto_ver=0.4.5 ARG indy_crypto_ver=0.4.5 -ARG token_ver=0.9.6~18 -ARG fees_ver=0.9.6~18 +ARG token_ver=0.9.6~25 +ARG fees_ver=0.9.6~25 # Install environment RUN apt-get update -y && apt-get install -y \ diff --git a/libsovtoken/tests/utils/payment/fees.rs b/libsovtoken/tests/utils/payment/fees.rs index 7ca661123..a748124f6 100644 --- a/libsovtoken/tests/utils/payment/fees.rs +++ b/libsovtoken/tests/utils/payment/fees.rs @@ -98,7 +98,7 @@ fn _get_default_ledger_auth_rules(pool_handle: i32) { let constraints = get_auth_rule_response["result"]["data"].as_object_mut().unwrap(); for (constraint_id, constraint) in constraints.iter_mut() { - let parts: Vec<&str> = constraint_id.split("--").collect(); + let parts: Vec<&str> = constraint_id[2..].split("--").collect(); let txn_type = parts[0].to_string(); let action = parts[1].to_string(); From 45586630840ac648a81e555cc819417f0a8a8522 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 20 May 2019 10:36:52 +0300 Subject: [PATCH 30/33] ST-545: Fixed broken tests Signed-off-by: artem.ivanov --- devops/indy-pool/Dockerfile | 4 ++-- libsovtoken/tests/build_mint_txn_handler_test.rs | 2 +- libsovtoken/tests/utils/payment/fees.rs | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/devops/indy-pool/Dockerfile b/devops/indy-pool/Dockerfile index 094b3909a..e65e5edbd 100644 --- a/devops/indy-pool/Dockerfile +++ b/devops/indy-pool/Dockerfile @@ -22,8 +22,8 @@ ARG uid=1000 ARG indy_stream=master -ARG indy_plenum_ver=1.8.0~dev791 -ARG indy_node_ver=1.8.0~dev932 +ARG indy_plenum_ver=1.8.0~dev794 +ARG indy_node_ver=1.8.0~dev935 ARG indy_anoncreds_ver=1.0.32 ARG python3_indy_crypto_ver=0.4.5 ARG indy_crypto_ver=0.4.5 diff --git a/libsovtoken/tests/build_mint_txn_handler_test.rs b/libsovtoken/tests/build_mint_txn_handler_test.rs index 1414f6444..63041f612 100644 --- a/libsovtoken/tests/build_mint_txn_handler_test.rs +++ b/libsovtoken/tests/build_mint_txn_handler_test.rs @@ -250,7 +250,7 @@ pub fn build_and_submit_mint_txn_works_with_empty_did() { let (mint_req, _) = indy::payments::build_mint_req( wallet.handle, - None, + Some(&dids[0]), &output_json, None, ).wait().unwrap(); diff --git a/libsovtoken/tests/utils/payment/fees.rs b/libsovtoken/tests/utils/payment/fees.rs index a748124f6..a8d8dbdf4 100644 --- a/libsovtoken/tests/utils/payment/fees.rs +++ b/libsovtoken/tests/utils/payment/fees.rs @@ -51,9 +51,11 @@ pub fn set_auth_rules_fee(pool_handle: i32, wallet_handle: i32, submitter_did: & for (txn_, fee_alias) in fees { if let Some(rules) = auth_rules.get(&txn_) { for auth_rule in rules { - let mut constraint = auth_rule.constraint.clone(); - _set_fee_to_constraint(&mut constraint, &fee_alias); - responses.push(_send_auth_rule(pool_handle, wallet_handle, submitter_did, auth_rule, &constraint)); + let mut constraint: ::serde_json::Value = auth_rule.constraint.clone(); + if !constraint.as_object().map(::serde_json::Map::is_empty).unwrap_or(true) { + _set_fee_to_constraint(&mut constraint, &fee_alias); + responses.push(_send_auth_rule(pool_handle, wallet_handle, submitter_did, auth_rule, &constraint)); + } } } } @@ -98,7 +100,7 @@ fn _get_default_ledger_auth_rules(pool_handle: i32) { let constraints = get_auth_rule_response["result"]["data"].as_object_mut().unwrap(); for (constraint_id, constraint) in constraints.iter_mut() { - let parts: Vec<&str> = constraint_id[2..].split("--").collect(); + let parts: Vec<&str> = constraint_id.split("--").collect(); let txn_type = parts[0].to_string(); let action = parts[1].to_string(); From f8c10606f6d39485bacf076793d975efa5603b38 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 20 May 2019 11:52:24 +0300 Subject: [PATCH 31/33] Updated ci docker files Signed-off-by: artem.ivanov --- devops/docker/base/xenial/Dockerfile | 6 +++--- devops/docker/ci/xenial/Dockerfile | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/devops/docker/base/xenial/Dockerfile b/devops/docker/base/xenial/Dockerfile index a7d72a88f..032dd1a13 100644 --- a/devops/docker/base/xenial/Dockerfile +++ b/devops/docker/base/xenial/Dockerfile @@ -21,9 +21,9 @@ RUN cd /tmp \ # need for libsodium to be reachable via pkg-config (sodiumoxide uses it) ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:$PKG_CONFIG_PATH # TODO ??? is it really needed -ENV LIBINDY_VERSION=1.8.2 +ENV LIBINDY_VERSION=1.8.3~1099 RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 68DB5E88 \ - && echo "deb https://repo.sovrin.org/sdk/deb xenial stable" >> /etc/apt/sources.list \ + && echo "deb https://repo.sovrin.org/sdk/deb xenial master" >> /etc/apt/sources.list \ && apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ libindy=${LIBINDY_VERSION} \ @@ -47,4 +47,4 @@ RUN cd /tmp/libsovtoken \ # TODO CMD ENTRYPOINT ... -ENV LIBSOVTOKEN_BASE_ENV_VERSION=0.19.0 +ENV LIBSOVTOKEN_BASE_ENV_VERSION=0.20.0 diff --git a/devops/docker/ci/xenial/Dockerfile b/devops/docker/ci/xenial/Dockerfile index 4da427a47..f9e0e02d7 100644 --- a/devops/docker/ci/xenial/Dockerfile +++ b/devops/docker/ci/xenial/Dockerfile @@ -1,4 +1,4 @@ -FROM sovrin/libsovtoken:base-xenial-0.19.0 +FROM sovrin/libsovtoken:base-xenial-0.20.0 # TODO LABEL maintainer="Name " ARG LIBINDY_CRYPTO_VERSION @@ -36,10 +36,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # or python3-rocksdb are not specified here) ENV LIBINDY_CRYPTO_VERSION ${LIBINDY_CRYPTO_VERSION:-0.4.5} ENV PYTHON3_INDY_CRYPTO_VERSION ${PYTHON3_INDY_CRYPTO_VERSION:-0.4.5} -ENV INDY_PLENUM_VERSION ${INDY_PLENUM_VERSION:-1.8.0~dev780} +ENV INDY_PLENUM_VERSION ${INDY_PLENUM_VERSION:-1.8.0~dev794} ENV INDY_ANONCREDS_VERSION ${INDY_ANONCREDS_VERSION:-1.0.32} -ENV INDY_NODE_VERSION ${INDY_NODE_VERSION:-1.8.0~dev920} -ENV TOKEN_VER ${TOKEN_VER:-0.9.6~18} +ENV INDY_NODE_VERSION ${INDY_NODE_VERSION:-1.8.0~dev935} +ENV TOKEN_VER ${TOKEN_VER:-0.9.6~25} RUN echo "deb https://repo.sovrin.org/sdk/deb xenial master" >> /etc/apt/sources.list RUN echo "deb https://repo.sovrin.org/deb xenial master" >> /etc/apt/sources.list \ && apt-get update && apt-get install -y --no-install-recommends \ @@ -69,4 +69,4 @@ COPY libsovtoken-ci-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/libsovtoken-ci-entrypoint.sh ENTRYPOINT ["libsovtoken-ci-entrypoint.sh"] -ENV LIBSOVTOKEN_CI_ENV_VERSION=0.56.0 +ENV LIBSOVTOKEN_CI_ENV_VERSION=0.57.0 From 7b2134a8d6a3a97fcbdfd5d20975a36bd82e133f Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 20 May 2019 13:07:09 +0300 Subject: [PATCH 32/33] Updated versions of libindy Signed-off-by: artem.ivanov --- devops/Makefile | 2 +- devops/aws-codebuild/Jenkinsfile.cd | 2 +- devops/aws-codebuild/Jenkinsfile.ci | 2 +- libsovtoken/Cargo.toml | 4 ++-- libsovtoken/build_scripts/ios/mac/shared.functions.sh | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/devops/Makefile b/devops/Makefile index 6084d86c1..5f1427b62 100644 --- a/devops/Makefile +++ b/devops/Makefile @@ -45,7 +45,7 @@ FPM_P_VENDOR := Sovrin FPM_P_DESCRIPTION := libsovtoken written in Rust FPM_P_NAME = $(PACKAGE_NAME) FPM_P_VERSION ?= $(SRC_VERSION) -FPM_P_DEPENDS = libindy(>=1.8.2~1045) +FPM_P_DEPENDS = libindy(>=1.8.3~1099) FPM_P_OUTPUT_DIR = $(LIB_TARGET_DIR) FPM_ARGS = $(LIB_DYNAMIC)=/usr/lib/ diff --git a/devops/aws-codebuild/Jenkinsfile.cd b/devops/aws-codebuild/Jenkinsfile.cd index ef4b03440..fa56b61d2 100644 --- a/devops/aws-codebuild/Jenkinsfile.cd +++ b/devops/aws-codebuild/Jenkinsfile.cd @@ -16,7 +16,7 @@ gitHubUserCredId = env.GITHUB_BOT_USER ?: 'sovbot-github' sovrinPackagingRepo = env.SOVRIN_PACKAGING_REPO ?: 'https://github.com/sovrin-foundation/sovrin-packaging' sovrinPackagingBranch = env.SOVRIN_PACKAGING_BRANCH ?: 'master' LIBINDY_STREAM = "master" -LIBINDY_VERSION = "1.8.2-1064" +LIBINDY_VERSION = "1.8.3-1099" def downloadPackagingUtils() { git branch: sovrinPackagingBranch, credentialsId: gitHubUserCredId, url: sovrinPackagingRepo diff --git a/devops/aws-codebuild/Jenkinsfile.ci b/devops/aws-codebuild/Jenkinsfile.ci index 3b0a15df2..4957696e0 100644 --- a/devops/aws-codebuild/Jenkinsfile.ci +++ b/devops/aws-codebuild/Jenkinsfile.ci @@ -8,7 +8,7 @@ logger = sovLibrary.Logger.new(this) notifier = sovLibrary.Notifier.new(this) logger.setGlobalLevel('TRACE') LIBINDY_STREAM = "master" -LIBINDY_VERSION = "1.8.2-1064" +LIBINDY_VERSION = "1.8.3-1099" def nodeLabels = [ codeBuild: env.LIBSOVTOKEN_CODEBUILD_NODE_LABEL ?: 'codebuild', diff --git a/libsovtoken/Cargo.toml b/libsovtoken/Cargo.toml index 7029ac168..0d5b9b1e1 100644 --- a/libsovtoken/Cargo.toml +++ b/libsovtoken/Cargo.toml @@ -28,8 +28,8 @@ libc = "0.2.41" log = "0.4.6" openssl = "0.10.20" rand = "0.3" -indy-sys = "1.8.2" -indy = "1.8.2" +indy-sys = "1.8.3-dev-1099" +indy = "1.8.3-dev-1099" serde = "1.0.89" serde_derive = "1.0.89" serde_json = "1.0.39" diff --git a/libsovtoken/build_scripts/ios/mac/shared.functions.sh b/libsovtoken/build_scripts/ios/mac/shared.functions.sh index 6573cefb4..0fef3e720 100644 --- a/libsovtoken/build_scripts/ios/mac/shared.functions.sh +++ b/libsovtoken/build_scripts/ios/mac/shared.functions.sh @@ -1,6 +1,6 @@ #!/bin/sh -export LIBINDY_IOS_BUILD_URL="https://repo.sovrin.org/ios/libindy/stable/libindy-core/1.8.2/libindy.tar.gz" +export LIBINDY_IOS_BUILD_URL="https://repo.sovrin.org/ios/libindy/stable/libindy-core/1.8.3/libindy.tar.gz" export LIBINDY_FILE=$(basename ${LIBINDY_IOS_BUILD_URL}) export LIBINDY_VERSION=$(basename $(dirname ${LIBINDY_IOS_BUILD_URL})) export BUILD_CACHE=~/.build_libvxc/ioscache From 1f8c4f17f9b696ddfa12a904ed8c4903fdbfffaa Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 21 May 2019 10:03:32 +0300 Subject: [PATCH 33/33] ST-552: Updated set_fees builder to accept any aliases Signed-off-by: artem.ivanov --- libsovtoken/src/api/mod.rs | 2 +- .../src/logic/config/set_fees_config.rs | 55 ++++++------------- libsovtoken/src/logic/set_fees.rs | 28 +--------- .../tests/build_fees_txn_handler_test.rs | 30 ++++++++-- 4 files changed, 45 insertions(+), 70 deletions(-) diff --git a/libsovtoken/src/api/mod.rs b/libsovtoken/src/api/mod.rs index 032fd3615..0e2046d72 100644 --- a/libsovtoken/src/api/mod.rs +++ b/libsovtoken/src/api/mod.rs @@ -661,7 +661,7 @@ pub extern "C" fn build_get_txn_fees_handler( let did = match opt_res_to_res_opt!(did) { Ok(did) => did, - Err(_e) => None + Err(_) => None }; let did = Some(did.unwrap_or(Did::new("LibsovtokenDid11111111".to_string()))); diff --git a/libsovtoken/src/logic/config/set_fees_config.rs b/libsovtoken/src/logic/config/set_fees_config.rs index def25eba9..c9262cf88 100644 --- a/libsovtoken/src/logic/config/set_fees_config.rs +++ b/libsovtoken/src/logic/config/set_fees_config.rs @@ -89,8 +89,7 @@ impl SetFees { /** Validate `self.fees`. - Checks `self.fees` is not empty and the keys are string - integers. + Checks `self.fees` is not empty. ## Examples @@ -110,25 +109,6 @@ impl SetFees { assert_eq!(SetFeesError::Empty, validated.unwrap_err()); ``` - #### Fees with non-string-integer keys - Returns a [`SetFeesError::KeyNotInteger`]. - ``` - use std::collections::HashMap; - use sovtoken::logic::config::set_fees_config::{ - SetFees, - SetFeesError, - }; - - let mut fees = HashMap::new(); - // Key should be "10001" - let key = String::from("XFER_PUBLIC"); - fees.insert(key.clone(), 10); - let set_fees = SetFees::new(fees); - let validated = set_fees.validate(); - - assert_eq!(SetFeesError::KeyNotInteger(key), validated.unwrap_err()) - ``` - #### Valid Fees ``` use std::collections::HashMap; @@ -148,23 +128,12 @@ impl SetFees { ``` [`SetFeesError::Empty`]: ./enum.SetFeesError.html#variant.Empty - [`SetFeesError::KeyNotInteger`]: ./enum.SetFeesError.html#variant.KeyNotInteger */ pub fn validate(self) -> Result { if self.fees.is_empty() { return Err(SetFeesError::Empty); } - { - let key_not_integer = self.fees - .keys() - .find(|&key| key.parse::().is_err()); - - if let Some(key) = key_not_integer { - return Err(SetFeesError::KeyNotInteger(key.to_owned())); - } - } - return Ok(self); } @@ -175,14 +144,12 @@ impl SetFees { ### Includes - `SetFeesError::Empty` - - `SetFeesError::KeyNotInteger(&str)` [`SetFees::validate`]: ./struct.SetFees.html#method.validate */ #[derive(Debug, PartialEq, Eq)] pub enum SetFeesError { Empty, - KeyNotInteger(String) } impl fmt::Display for SetFeesError { @@ -195,7 +162,6 @@ impl Error for SetFeesError { fn description(&self) -> &str { match self { &SetFeesError::Empty => "Set fees was empty.", - &SetFeesError::KeyNotInteger(_) => "A Set fees key wasn't a integer string.", } } } @@ -225,22 +191,33 @@ mod fees_config_test { } #[test] - fn test_validation_fees_key_not_string_integer() { + fn test_validation_fees_key_string_integer() { + let set_fees_json = json!({ + "1000": 10, + }); + let hash_map: SetFeesMap = serde_json::from_value(set_fees_json).unwrap(); + let set_fees = SetFees::new(hash_map); + assert!(set_fees.validate().is_ok()); + } + + #[test] + fn test_validation_fees_key_aliases() { let set_fees_json = json!({ "XFER_PUBLIC": 10, + "ALIAS": 10, }); - let expected = SetFeesError::KeyNotInteger(String::from("XFER_PUBLIC")); let hash_map: SetFeesMap = serde_json::from_value(set_fees_json).unwrap(); let set_fees = SetFees::new(hash_map); - assert_eq!(expected, set_fees.validate().unwrap_err()); + assert!(set_fees.validate().is_ok()); } #[test] fn create_valid_set_fees_request() { let set_fees_json = json!({ "3": 10, - "1000": 12 + "1000": 12, + "ALIAS": 10, }); let expected = set_fees_json.clone(); diff --git a/libsovtoken/src/logic/set_fees.rs b/libsovtoken/src/logic/set_fees.rs index 7798a14c5..6c08b30bd 100644 --- a/libsovtoken/src/logic/set_fees.rs +++ b/libsovtoken/src/logic/set_fees.rs @@ -8,27 +8,6 @@ use serde_json; use utils::constants::general::{JsonCallback, JsonCallbackUnwrapped}; use utils::ffi_support::string_from_char_ptr; -const NYM: &'static str = "1"; -const ATTRIB: &'static str = "100"; -const SCHEMA: &'static str = "101"; -const CRED_DEF: &'static str = "102"; -const REVOC_REG_DEF: &'static str = "113"; -const REVOC_REG_ENTRY: &'static str = "114"; -const XFER_PUBLIC: &'static str = "10001"; - -fn txn_name_to_code(txn: &str) -> String { - match txn { - "NYM" => NYM.to_string(), - "ATTRIB" => ATTRIB.to_string(), - "SCHEMA" => SCHEMA.to_string(), - "CRED_DEF" => CRED_DEF.to_string(), - "REVOC_REG_DEF" => REVOC_REG_DEF.to_string(), - "REVOC_REG_ENTRY" => REVOC_REG_ENTRY.to_string(), - "XFER_PUBLIC" => XFER_PUBLIC.to_string(), - val @ _ => val.to_string() - } -} - type DeserializedArguments = (Option, SetFees, JsonCallbackUnwrapped); pub fn deserialize_inputs( @@ -51,9 +30,6 @@ pub fn deserialize_inputs( let set_fees_map: SetFeesMap = serde_json::from_str(&set_fees_json).map_err(map_err_err!()) .or(Err(ErrorCode::CommonInvalidStructure))?; - let set_fees_map: SetFeesMap = set_fees_map.iter() - .map(|(key, val)| (txn_name_to_code(key), val.clone())).collect(); - let set_fees = SetFees::new(set_fees_map) .validate().map_err(map_err_err!()) .or(Err(ErrorCode::CommonInvalidStructure))?; @@ -135,7 +111,7 @@ mod test_deserialize_inputs { } #[test] - fn deserialize_fees_key_not_string_int() { + fn deserialize_fees_key_alias() { let invalid_fees = json_c_pointer!({ "XFER_PUBLIC": 5, "3": 1, @@ -144,7 +120,7 @@ mod test_deserialize_inputs { let (_, fees, _) = call_deserialize_inputs(None, Some(invalid_fees), None).unwrap(); assert_eq!(fees.fees.len(), 2); - assert_eq!(fees.fees.get("10001"), Some(&5)); + assert_eq!(fees.fees.get("XFER_PUBLIC"), Some(&5)); assert_eq!(fees.fees.get("3"), Some(&1)); } diff --git a/libsovtoken/tests/build_fees_txn_handler_test.rs b/libsovtoken/tests/build_fees_txn_handler_test.rs index a3b3461c3..6da5e92d9 100644 --- a/libsovtoken/tests/build_fees_txn_handler_test.rs +++ b/libsovtoken/tests/build_fees_txn_handler_test.rs @@ -108,7 +108,29 @@ fn add_fees_json() { assert_eq!(&expected_operation, request_value.get("operation").unwrap()); } +#[test] +fn add_fees_json_for_any_key() { + sovtoken::api::sovtoken_init(); + let fees = json!({ + "3": 6, + "TXN_ALIAS": 12, + "TXN ALIAS WITH SPACE": 12, + }); + let expected_operation = json!({ + "type": "20000", + "fees": fees, + }); + let did = bs58::encode("1234567890123456").into_string(); + let (ec_initial, receiver) = call_set_fees(&did, fees); + let (ec_callback, fees_request) = receiver.recv().unwrap(); + + let request_value: serde_json::value::Value = serde_json::from_str(&fees_request).unwrap(); + + assert_eq!(ErrorCode::Success, ec_initial); + assert_eq!(ErrorCode::Success, ec_callback); + assert_eq!(&expected_operation, request_value.get("operation").unwrap()); +} #[test] pub fn build_and_submit_set_fees() { @@ -167,8 +189,8 @@ pub fn build_and_submit_set_fees_with_names() { let current_fees = fees::get_fees(&wallet, pool_handle, Some(dids[0])); let current_fees_value: serde_json::Value = serde_json::from_str(¤t_fees).unwrap(); - assert_eq!(current_fees_value["1"].as_u64().unwrap(), 1); - assert_eq!(current_fees_value["100"].as_u64().unwrap(), 2); + assert_eq!(current_fees_value["NYM"].as_u64().unwrap(), 1); + assert_eq!(current_fees_value["ATTRIB"].as_u64().unwrap(), 2); let fees = json!({ "NYM": 0, @@ -202,8 +224,8 @@ pub fn build_and_submit_set_fees_with_empty_did() { let current_fees = fees::get_fees(&wallet, pool_handle, None); let current_fees_value: serde_json::Value = serde_json::from_str(¤t_fees).unwrap(); - assert_eq!(current_fees_value["1"].as_u64().unwrap(), 1); - assert_eq!(current_fees_value["100"].as_u64().unwrap(), 2); + assert_eq!(current_fees_value["NYM"].as_u64().unwrap(), 1); + assert_eq!(current_fees_value["ATTRIB"].as_u64().unwrap(), 2); let fees = json!({ "NYM": 0,