From 8fbe14c8f5441ffba40e1cc45de3778d9b55682a Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 12 Jun 2020 13:15:25 +0300 Subject: [PATCH 01/20] rename sigma-tree-c to sigma-ios; --- Cargo.toml | 2 +- {sigma-tree-c => sigma-ios}/Cargo.toml | 4 ++-- {sigma-tree-c => sigma-ios}/src/lib.rs | 0 {sigma-tree-c => sigma-ios}/src/misc_c.rs | 0 sigma-wasm/Cargo.toml | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename {sigma-tree-c => sigma-ios}/Cargo.toml (83%) rename {sigma-tree-c => sigma-ios}/src/lib.rs (100%) rename {sigma-tree-c => sigma-ios}/src/misc_c.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 08e944975..6afa8be3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,6 @@ members = [ "sigma-ser", "sigma-tree", "sigma-wasm", - "sigma-tree-c", + "sigma-ios", "sigma-testutil", ] diff --git a/sigma-tree-c/Cargo.toml b/sigma-ios/Cargo.toml similarity index 83% rename from sigma-tree-c/Cargo.toml rename to sigma-ios/Cargo.toml index c0ca6eb12..0b31ec1f1 100644 --- a/sigma-tree-c/Cargo.toml +++ b/sigma-ios/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "sigma-tree-c" +name = "sigma-ios" version = "0.1.0" authors = ["Denys Zadorozhnyi "] edition = "2018" -description = "C bindings for sigma-tree" +description = "Sigma C bindings for iOS" [lib] crate-type = ["staticlib"] diff --git a/sigma-tree-c/src/lib.rs b/sigma-ios/src/lib.rs similarity index 100% rename from sigma-tree-c/src/lib.rs rename to sigma-ios/src/lib.rs diff --git a/sigma-tree-c/src/misc_c.rs b/sigma-ios/src/misc_c.rs similarity index 100% rename from sigma-tree-c/src/misc_c.rs rename to sigma-ios/src/misc_c.rs diff --git a/sigma-wasm/Cargo.toml b/sigma-wasm/Cargo.toml index 811d8eb13..299110c7d 100644 --- a/sigma-wasm/Cargo.toml +++ b/sigma-wasm/Cargo.toml @@ -3,7 +3,7 @@ name = "sigma-tree-wasm" version = "0.1.0" authors = ["Denys Zadorozhnyi "] edition = "2018" -description = "WASM bindings for sigma-tree" +description = "Sigma WASM bindings" [lib] crate-type = ["cdylib", "rlib"] From ff280b98427d00dfb9dcee44a48c607b31266bfb Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 12 Jun 2020 17:47:56 +0300 Subject: [PATCH 02/20] add cbindgen harness; --- sigma-ios/Cargo.toml | 3 + sigma-ios/build.rs | 15 +++++ sigma-ios/cbindgen.toml | 144 ++++++++++++++++++++++++++++++++++++++++ sigma-ios/h/sigma.h | 9 +++ sigma-ios/src/lib.rs | 7 +- sigma-ios/src/misc_c.rs | 6 -- 6 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 sigma-ios/build.rs create mode 100644 sigma-ios/cbindgen.toml create mode 100644 sigma-ios/h/sigma.h diff --git a/sigma-ios/Cargo.toml b/sigma-ios/Cargo.toml index 0b31ec1f1..493630095 100644 --- a/sigma-ios/Cargo.toml +++ b/sigma-ios/Cargo.toml @@ -4,11 +4,13 @@ version = "0.1.0" authors = ["Denys Zadorozhnyi "] edition = "2018" description = "Sigma C bindings for iOS" +build = "build.rs" [lib] crate-type = ["staticlib"] [dependencies] +ffi_helpers = "0.2" sigma-tree = { path = "../sigma-tree", version = "0.1.0" } [build-dependencies] @@ -17,3 +19,4 @@ cbindgen = "0.14" [profile.release] # Tell `rustc` to optimize for small code size. opt-level = "s" +lto = true diff --git a/sigma-ios/build.rs b/sigma-ios/build.rs new file mode 100644 index 000000000..d8a74dc42 --- /dev/null +++ b/sigma-ios/build.rs @@ -0,0 +1,15 @@ +extern crate cbindgen; + +use std::env; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let config = cbindgen::Config::from_file("cbindgen.toml").expect("No cbindgen.toml found"); + + cbindgen::Builder::new() + .with_crate(crate_dir) + .with_config(config) + .generate() + .expect("Unable to generate bindings") + .write_to_file("h/sigma.h"); +} diff --git a/sigma-ios/cbindgen.toml b/sigma-ios/cbindgen.toml new file mode 100644 index 000000000..2aff65bea --- /dev/null +++ b/sigma-ios/cbindgen.toml @@ -0,0 +1,144 @@ +# This is a template cbindgen.toml file with all of the default values. +# Some values are commented out because their absence is the real default. +# +# See https://github.com/eqrion/cbindgen/blob/master/docs.md#cbindgentoml +# for detailed documentation of every option here. + + +language = "C" + + + +############## Options for Wrapping the Contents of the Header ################# + +# header = "/* Text to put at the beginning of the generated file. Probably a license. */" +# trailer = "/* Text to put at the end of the generated file */" +# include_guard = "my_bindings_h" +# pragma_once = true +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" +include_version = false +# namespace = "my_namespace" +namespaces = [] +using_namespaces = [] +sys_includes = [] +includes = [] +no_includes = false +after_includes = "" + + + + +############################ Code Style Options ################################ + +braces = "SameLine" +line_length = 100 +tab_width = 2 +documentation_style = "auto" + + + + + +############################# Codegen Options ################################## + +style = "both" + + + +[defines] +# "target_os = freebsd" = "DEFINE_FREEBSD" +# "feature = serde" = "DEFINE_SERDE" + + + +[export] +include = [] +exclude = [] +# prefix = "CAPI_" +item_types = [] +renaming_overrides_prefixing = false + + + +[export.rename] + + + +[export.body] + + + + +[fn] +rename_args = "None" +# must_use = "MUST_USE_FUNC" +# prefix = "START_FUNC" +# postfix = "END_FUNC" +args = "auto" +sort_by = "Name" + + + + +[struct] +rename_fields = "None" +# must_use = "MUST_USE_STRUCT" +derive_constructor = false +derive_eq = false +derive_neq = false +derive_lt = false +derive_lte = false +derive_gt = false +derive_gte = false + + + + +[enum] +rename_variants = "None" +# must_use = "MUST_USE_ENUM" +add_sentinel = false +prefix_with_name = false +derive_helper_methods = false +derive_const_casts = false +derive_mut_casts = false +# cast_assert_name = "ASSERT" +derive_tagged_enum_destructor = false +derive_tagged_enum_copy_constructor = false +enum_class = true +private_default_tagged_enum_constructor = false + + + + +[const] +allow_static_const = true +allow_constexpr = false + + + + +[macro_expansion] +bitflags = false + + + + + + +############## Options for How Your Rust library Should Be Parsed ############## + +[parse] +parse_deps = false +# include = [] +exclude = [] +clean = false +extra_bindings = [] + + + +[parse.expand] +crates = [] +all_features = false +default_features = true +features = [] diff --git a/sigma-ios/h/sigma.h b/sigma-ios/h/sigma.h new file mode 100644 index 000000000..b404d8a5c --- /dev/null +++ b/sigma-ios/h/sigma.h @@ -0,0 +1,9 @@ +/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ + +#include +#include +#include +#include + + +long long add_numbers(int x, int y); diff --git a/sigma-ios/src/lib.rs b/sigma-ios/src/lib.rs index 531265926..a0d2511b2 100644 --- a/sigma-ios/src/lib.rs +++ b/sigma-ios/src/lib.rs @@ -1,3 +1,6 @@ -mod misc_c; +use std::os::raw::{c_int, c_longlong}; -pub use misc_c::*; +#[no_mangle] +pub extern "C" fn add_numbers(x: c_int, y: c_int) -> c_longlong { + x as i64 + y as i64 +} diff --git a/sigma-ios/src/misc_c.rs b/sigma-ios/src/misc_c.rs index a0d2511b2..e69de29bb 100644 --- a/sigma-ios/src/misc_c.rs +++ b/sigma-ios/src/misc_c.rs @@ -1,6 +0,0 @@ -use std::os::raw::{c_int, c_longlong}; - -#[no_mangle] -pub extern "C" fn add_numbers(x: c_int, y: c_int) -> c_longlong { - x as i64 + y as i64 -} From b87882e3570aba3efc56fc8762a97a006af8a6e7 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 12 Jun 2020 17:57:50 +0300 Subject: [PATCH 03/20] add coding conventions; --- sigma-ios/h/sigma.h | 3 +++ sigma-ios/src/lib.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/sigma-ios/h/sigma.h b/sigma-ios/h/sigma.h index b404d8a5c..1e3056818 100644 --- a/sigma-ios/h/sigma.h +++ b/sigma-ios/h/sigma.h @@ -6,4 +6,7 @@ #include +/** + * test + */ long long add_numbers(int x, int y); diff --git a/sigma-ios/src/lib.rs b/sigma-ios/src/lib.rs index a0d2511b2..c3a62af1d 100644 --- a/sigma-ios/src/lib.rs +++ b/sigma-ios/src/lib.rs @@ -1,5 +1,19 @@ +//! WASM bindings for sigma-tree + +// Coding conventions +#![deny(non_upper_case_globals)] +#![deny(non_camel_case_types)] +#![deny(non_snake_case)] +#![deny(unused_mut)] +#![deny(dead_code)] +#![deny(unused_imports)] +#![deny(missing_docs)] + +// use sigma_tree::chain; + use std::os::raw::{c_int, c_longlong}; +/// test #[no_mangle] pub extern "C" fn add_numbers(x: c_int, y: c_int) -> c_longlong { x as i64 + y as i64 From 49f691dd24fc5ec69abf1fe2776d9cc97793b0c0 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sat, 13 Jun 2020 15:53:58 +0300 Subject: [PATCH 04/20] fix sigma-wasm crate name; --- sigma-wasm/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigma-wasm/Cargo.toml b/sigma-wasm/Cargo.toml index 299110c7d..7f5ec2094 100644 --- a/sigma-wasm/Cargo.toml +++ b/sigma-wasm/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sigma-tree-wasm" +name = "sigma-wasm" version = "0.1.0" authors = ["Denys Zadorozhnyi "] edition = "2018" From 2c8e692cfc51d070ef89db50fb706a287750058c Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sat, 13 Jun 2020 16:10:12 +0300 Subject: [PATCH 05/20] establish ergo-wallet crate; rename sigma-wasm to ergo-wallet-wasm and sigma-ios to ergo-wallet-c; --- Cargo.toml | 5 +++-- {sigma-ios => bindings/ergo-wallet-c}/Cargo.toml | 6 +++--- {sigma-ios => bindings/ergo-wallet-c}/build.rs | 0 {sigma-ios => bindings/ergo-wallet-c}/cbindgen.toml | 0 {sigma-ios => bindings/ergo-wallet-c}/h/sigma.h | 0 {sigma-ios => bindings/ergo-wallet-c}/src/lib.rs | 0 {sigma-ios => bindings/ergo-wallet-c}/src/misc_c.rs | 0 {sigma-wasm => bindings/ergo-wallet-wasm}/.babelrc | 0 {sigma-wasm => bindings/ergo-wallet-wasm}/Cargo.toml | 8 ++++---- {sigma-wasm => bindings/ergo-wallet-wasm}/README.md | 0 {sigma-wasm => bindings/ergo-wallet-wasm}/jsdoc.json | 0 .../ergo-wallet-wasm}/package.json | 0 {sigma-wasm => bindings/ergo-wallet-wasm}/src/lib.rs | 0 .../ergo-wallet-wasm}/src/utils.rs | 0 .../ergo-wallet-wasm}/tests/index.js | 0 .../ergo-wallet-wasm}/tests/test_transaction.js | 0 .../ergo-wallet-wasm}/tests/transaction.rs | 4 ++-- .../ergo-wallet-wasm}/webpack.config.js | 0 ergo-wallet/Cargo.toml | 11 +++++++++++ ergo-wallet/src/lib.rs | 0 20 files changed, 23 insertions(+), 11 deletions(-) rename {sigma-ios => bindings/ergo-wallet-c}/Cargo.toml (72%) rename {sigma-ios => bindings/ergo-wallet-c}/build.rs (100%) rename {sigma-ios => bindings/ergo-wallet-c}/cbindgen.toml (100%) rename {sigma-ios => bindings/ergo-wallet-c}/h/sigma.h (100%) rename {sigma-ios => bindings/ergo-wallet-c}/src/lib.rs (100%) rename {sigma-ios => bindings/ergo-wallet-c}/src/misc_c.rs (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/.babelrc (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/Cargo.toml (86%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/README.md (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/jsdoc.json (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/package.json (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/src/lib.rs (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/src/utils.rs (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/tests/index.js (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/tests/test_transaction.js (100%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/tests/transaction.rs (93%) rename {sigma-wasm => bindings/ergo-wallet-wasm}/webpack.config.js (100%) create mode 100644 ergo-wallet/Cargo.toml create mode 100644 ergo-wallet/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 6afa8be3b..aee1743b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,8 @@ members = [ "sigma-ser", "sigma-tree", - "sigma-wasm", - "sigma-ios", + "ergo-wallet", + "bindings/ergo-wallet-wasm", + "bindings/ergo-wallet-c", "sigma-testutil", ] diff --git a/sigma-ios/Cargo.toml b/bindings/ergo-wallet-c/Cargo.toml similarity index 72% rename from sigma-ios/Cargo.toml rename to bindings/ergo-wallet-c/Cargo.toml index 493630095..9699f4a6a 100644 --- a/sigma-ios/Cargo.toml +++ b/bindings/ergo-wallet-c/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "sigma-ios" +name = "ergo-wallet-c" version = "0.1.0" authors = ["Denys Zadorozhnyi "] edition = "2018" -description = "Sigma C bindings for iOS" +description = "Ergo wallet C bindings" build = "build.rs" [lib] @@ -11,7 +11,7 @@ crate-type = ["staticlib"] [dependencies] ffi_helpers = "0.2" -sigma-tree = { path = "../sigma-tree", version = "0.1.0" } +sigma-tree = { path = "../../sigma-tree", version = "0.1.0" } [build-dependencies] cbindgen = "0.14" diff --git a/sigma-ios/build.rs b/bindings/ergo-wallet-c/build.rs similarity index 100% rename from sigma-ios/build.rs rename to bindings/ergo-wallet-c/build.rs diff --git a/sigma-ios/cbindgen.toml b/bindings/ergo-wallet-c/cbindgen.toml similarity index 100% rename from sigma-ios/cbindgen.toml rename to bindings/ergo-wallet-c/cbindgen.toml diff --git a/sigma-ios/h/sigma.h b/bindings/ergo-wallet-c/h/sigma.h similarity index 100% rename from sigma-ios/h/sigma.h rename to bindings/ergo-wallet-c/h/sigma.h diff --git a/sigma-ios/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs similarity index 100% rename from sigma-ios/src/lib.rs rename to bindings/ergo-wallet-c/src/lib.rs diff --git a/sigma-ios/src/misc_c.rs b/bindings/ergo-wallet-c/src/misc_c.rs similarity index 100% rename from sigma-ios/src/misc_c.rs rename to bindings/ergo-wallet-c/src/misc_c.rs diff --git a/sigma-wasm/.babelrc b/bindings/ergo-wallet-wasm/.babelrc similarity index 100% rename from sigma-wasm/.babelrc rename to bindings/ergo-wallet-wasm/.babelrc diff --git a/sigma-wasm/Cargo.toml b/bindings/ergo-wallet-wasm/Cargo.toml similarity index 86% rename from sigma-wasm/Cargo.toml rename to bindings/ergo-wallet-wasm/Cargo.toml index 7f5ec2094..73a0b2f3c 100644 --- a/sigma-wasm/Cargo.toml +++ b/bindings/ergo-wallet-wasm/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "sigma-wasm" +name = "ergo-wallet-wasm" version = "0.1.0" authors = ["Denys Zadorozhnyi "] edition = "2018" -description = "Sigma WASM bindings" +description = "Ergo wallet WASM bindings" [lib] crate-type = ["cdylib", "rlib"] @@ -13,7 +13,7 @@ default = ["console_error_panic_hook"] [dependencies] serde = { version = "1.0", features = ["derive"]} -sigma-tree = { path = "../sigma-tree", features = ["with-serde"] } +sigma-tree = { path = "../../sigma-tree", features = ["with-serde"] } # used in elliptic-curve(in sigma-tree), compiled here with WASM support getrandom = {version = "0.1", features = ["wasm-bindgen"]} # The `console_error_panic_hook` crate provides better debugging of panics by @@ -29,7 +29,7 @@ features = ["serde-serialize"] [dev-dependencies] wasm-bindgen-test = "0.3.10" proptest-derive = "0.2" -sigma-testutil = { path = "../sigma-testutil" } +sigma-testutil = { path = "../../sigma-testutil" } [dev-dependencies.proptest] # wasm support, via https://altsysrq.github.io/proptest-book/proptest/wasm.html diff --git a/sigma-wasm/README.md b/bindings/ergo-wallet-wasm/README.md similarity index 100% rename from sigma-wasm/README.md rename to bindings/ergo-wallet-wasm/README.md diff --git a/sigma-wasm/jsdoc.json b/bindings/ergo-wallet-wasm/jsdoc.json similarity index 100% rename from sigma-wasm/jsdoc.json rename to bindings/ergo-wallet-wasm/jsdoc.json diff --git a/sigma-wasm/package.json b/bindings/ergo-wallet-wasm/package.json similarity index 100% rename from sigma-wasm/package.json rename to bindings/ergo-wallet-wasm/package.json diff --git a/sigma-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs similarity index 100% rename from sigma-wasm/src/lib.rs rename to bindings/ergo-wallet-wasm/src/lib.rs diff --git a/sigma-wasm/src/utils.rs b/bindings/ergo-wallet-wasm/src/utils.rs similarity index 100% rename from sigma-wasm/src/utils.rs rename to bindings/ergo-wallet-wasm/src/utils.rs diff --git a/sigma-wasm/tests/index.js b/bindings/ergo-wallet-wasm/tests/index.js similarity index 100% rename from sigma-wasm/tests/index.js rename to bindings/ergo-wallet-wasm/tests/index.js diff --git a/sigma-wasm/tests/test_transaction.js b/bindings/ergo-wallet-wasm/tests/test_transaction.js similarity index 100% rename from sigma-wasm/tests/test_transaction.js rename to bindings/ergo-wallet-wasm/tests/test_transaction.js diff --git a/sigma-wasm/tests/transaction.rs b/bindings/ergo-wallet-wasm/tests/transaction.rs similarity index 93% rename from sigma-wasm/tests/transaction.rs rename to bindings/ergo-wallet-wasm/tests/transaction.rs index 5a409d991..bdd9de813 100644 --- a/sigma-wasm/tests/transaction.rs +++ b/bindings/ergo-wallet-wasm/tests/transaction.rs @@ -1,8 +1,8 @@ //! Test suite for the Web and headless browsers. -extern crate sigma_tree_wasm; +extern crate ergo_wallet_wasm; extern crate wasm_bindgen_test; -use sigma_tree_wasm::*; +use ergo_wallet_wasm::*; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); diff --git a/sigma-wasm/webpack.config.js b/bindings/ergo-wallet-wasm/webpack.config.js similarity index 100% rename from sigma-wasm/webpack.config.js rename to bindings/ergo-wallet-wasm/webpack.config.js diff --git a/ergo-wallet/Cargo.toml b/ergo-wallet/Cargo.toml new file mode 100644 index 000000000..165087774 --- /dev/null +++ b/ergo-wallet/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "ergo-wallet" +version = "0.1.0" +authors = ["Denys Zadorozhnyi "] +edition = "2018" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] + diff --git a/ergo-wallet/src/lib.rs b/ergo-wallet/src/lib.rs new file mode 100644 index 000000000..e69de29bb From 39b555ec95fdf153b0d2d236ecf9a842cc6a0b47 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sat, 13 Jun 2020 17:13:15 +0300 Subject: [PATCH 06/20] move SecretKey from sigma-tree to ergo-wallet; --- bindings/ergo-wallet-wasm/Cargo.toml | 1 + bindings/ergo-wallet-wasm/src/lib.rs | 4 ++-- ergo-wallet/Cargo.toml | 4 ++++ ergo-wallet/src/lib.rs | 15 ++++++++++++ .../chain => ergo-wallet/src}/secret_key.rs | 2 +- sigma-tree/src/chain.rs | 2 -- sigma-tree/src/lib.rs | 2 +- sigma-tree/src/sigma_protocol.rs | 23 +++++++++++++++++++ 8 files changed, 47 insertions(+), 6 deletions(-) rename {sigma-tree/src/chain => ergo-wallet/src}/secret_key.rs (88%) diff --git a/bindings/ergo-wallet-wasm/Cargo.toml b/bindings/ergo-wallet-wasm/Cargo.toml index 73a0b2f3c..9a919732a 100644 --- a/bindings/ergo-wallet-wasm/Cargo.toml +++ b/bindings/ergo-wallet-wasm/Cargo.toml @@ -13,6 +13,7 @@ default = ["console_error_panic_hook"] [dependencies] serde = { version = "1.0", features = ["derive"]} +ergo-wallet = { path = "../../ergo-wallet", features = ["with-serde"] } sigma-tree = { path = "../../sigma-tree", features = ["with-serde"] } # used in elliptic-curve(in sigma-tree), compiled here with WASM support getrandom = {version = "0.1", features = ["wasm-bindgen"]} diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index 70130511b..7baf8a8c0 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -75,14 +75,14 @@ impl Address { /// Secret key for prover #[wasm_bindgen] -pub struct SecretKey(chain::SecretKey); +pub struct SecretKey(ergo_wallet::SecretKey); #[wasm_bindgen] impl SecretKey { /// Decode from string pub fn parse(_: &str) -> Result { // not implemented, see https://github.com/ergoplatform/sigma-rust/issues/33 - Ok(SecretKey(chain::SecretKey::random_dlog())) + Ok(SecretKey(ergo_wallet::SecretKey::random_dlog())) } } diff --git a/ergo-wallet/Cargo.toml b/ergo-wallet/Cargo.toml index 165087774..aab300320 100644 --- a/ergo-wallet/Cargo.toml +++ b/ergo-wallet/Cargo.toml @@ -8,4 +8,8 @@ edition = "2018" crate-type = ["cdylib", "rlib"] [dependencies] +serde = { version = "1.0", features = ["derive"], optional = true } +sigma-tree = { path = "../sigma-tree", features = ["with-serde"] } +[features] +with-serde = ["serde"] diff --git a/ergo-wallet/src/lib.rs b/ergo-wallet/src/lib.rs index e69de29bb..cf436bccf 100644 --- a/ergo-wallet/src/lib.rs +++ b/ergo-wallet/src/lib.rs @@ -0,0 +1,15 @@ +//! Ergo wallet + +// Coding conventions +#![forbid(unsafe_code)] +#![deny(non_upper_case_globals)] +#![deny(non_camel_case_types)] +#![deny(non_snake_case)] +#![deny(unused_mut)] +#![deny(dead_code)] +#![deny(unused_imports)] +#![deny(missing_docs)] + +mod secret_key; + +pub use secret_key::*; diff --git a/sigma-tree/src/chain/secret_key.rs b/ergo-wallet/src/secret_key.rs similarity index 88% rename from sigma-tree/src/chain/secret_key.rs rename to ergo-wallet/src/secret_key.rs index 0b34240f2..7d9edc1e6 100644 --- a/sigma-tree/src/chain/secret_key.rs +++ b/ergo-wallet/src/secret_key.rs @@ -1,4 +1,4 @@ -use crate::sigma_protocol::DlogProverInput; +use sigma_tree::sigma_protocol::DlogProverInput; /// Types of secrets pub enum SecretKey { diff --git a/sigma-tree/src/chain.rs b/sigma-tree/src/chain.rs index cf96834ee..9a91b094b 100644 --- a/sigma-tree/src/chain.rs +++ b/sigma-tree/src/chain.rs @@ -8,7 +8,6 @@ mod data_input; mod ergo_box; mod input; mod prover_result; -mod secret_key; mod token; mod transaction; @@ -17,5 +16,4 @@ pub use box_id::*; pub use contract::*; pub use ergo_box::*; pub use input::*; -pub use secret_key::*; pub use transaction::*; diff --git a/sigma-tree/src/lib.rs b/sigma-tree/src/lib.rs index b7e9cdd52..28bc96199 100644 --- a/sigma-tree/src/lib.rs +++ b/sigma-tree/src/lib.rs @@ -16,8 +16,8 @@ mod ecpoint; mod ergo_tree; mod eval; mod serialization; -mod sigma_protocol; mod types; pub mod chain; +pub mod sigma_protocol; pub use ergo_tree::*; diff --git a/sigma-tree/src/sigma_protocol.rs b/sigma-tree/src/sigma_protocol.rs index 7c6bd239e..b13bffb38 100644 --- a/sigma-tree/src/sigma_protocol.rs +++ b/sigma-tree/src/sigma_protocol.rs @@ -1,13 +1,17 @@ +//! Sigma protocols use k256::arithmetic::Scalar; use crate::{ecpoint::EcPoint, serialization::op_code::OpCode}; use std::convert::TryInto; +/// Secret key of discrete logarithm signature protocol pub struct DlogProverInput { + /// secret key value pub w: Scalar, } impl DlogProverInput { + /// generates random secret in the range [0, n), where n is DLog group order. pub fn random() -> DlogProverInput { let scalar = loop { // Generate a new secret key using the operating system's @@ -29,6 +33,7 @@ impl DlogProverInput { DlogProverInput { w: scalar } } + /// public key of discrete logarithm signature protocol #[allow(dead_code)] fn public_image(&self) -> ProveDlog { // test it, see https://github.com/ergoplatform/sigma-rust/issues/38 @@ -37,7 +42,9 @@ impl DlogProverInput { } } +/// Get public key for signature protocol pub trait PrivateInput { + /// public key fn public_image(&self) -> SigmaProofOfKnowledgeTree; } @@ -48,12 +55,15 @@ impl PrivateInput for DlogProverInput { } } +/// Construct a new SigmaBoolean value representing public key of discrete logarithm signature protocol. #[derive(PartialEq, Eq, Debug, Clone)] pub struct ProveDlog { + /// public key pub h: Box, } impl ProveDlog { + /// create new public key pub fn new(ecpoint: EcPoint) -> ProveDlog { ProveDlog { h: Box::new(ecpoint), @@ -61,6 +71,8 @@ impl ProveDlog { } } +/// Construct a new SigmaProp value representing public key of Diffie Hellman signature protocol. +/// Common input: (g,h,u,v) #[derive(PartialEq, Eq, Debug, Clone)] pub struct ProveDHTuple { gv: Box, @@ -69,19 +81,27 @@ pub struct ProveDHTuple { vv: Box, } +/// Sigma proposition #[derive(PartialEq, Eq, Debug, Clone)] pub enum SigmaProofOfKnowledgeTree { + /// public key of Diffie Hellman signature protocol ProveDHTuple(ProveDHTuple), + /// public key of discrete logarithm signature protocol ProveDlog(ProveDlog), } +/// Algebraic data type of sigma proposition expressions +/// Values of this type are used as values of SigmaProp type #[derive(PartialEq, Eq, Debug, Clone)] pub enum SigmaBoolean { + /// Sigma proposition ProofOfKnowledge(SigmaProofOfKnowledgeTree), + /// AND conjunction for sigma propositions CAND(Vec), } impl SigmaBoolean { + /// get OpCode for serialization pub fn op_code(&self) -> OpCode { match self { SigmaBoolean::ProofOfKnowledge(SigmaProofOfKnowledgeTree::ProveDlog(_)) => { @@ -92,14 +112,17 @@ impl SigmaBoolean { } } +/// Proposition which can be proven and verified by sigma protocol. #[derive(PartialEq, Eq, Debug, Clone)] pub struct SigmaProp(SigmaBoolean); impl SigmaProp { + /// create new sigma propostion from [`SigmaBoolean`] value pub fn new(sbool: SigmaBoolean) -> Self { SigmaProp { 0: sbool } } + /// get [`SigmaBoolean`] value pub fn value(&self) -> &SigmaBoolean { &self.0 } From 10c3257cc57f1e03d6bec407bbb0576027d2d5ca Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sat, 13 Jun 2020 17:14:33 +0300 Subject: [PATCH 07/20] fix paths in travis.yml; --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fefaf71a5..873852402 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,7 +61,7 @@ matrix: before_script: - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f script: - - cd sigma-wasm + - cd bindings/ergo-wallet-wasm - wasm-pack build - wasm-pack test --firefox --headless - wasm-pack test --firefox --headless --release @@ -82,7 +82,7 @@ matrix: before_script: - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f script: - - cd sigma-wasm + - cd bindings/ergo-wallet-wasm - wasm-pack build - npm install && npm run test From 01753dc859f6d0f43198d95217c084978d7339b9 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sat, 13 Jun 2020 17:25:58 +0300 Subject: [PATCH 08/20] add data inputs parameter(TxDataInputs) to new_signed_transaction; --- bindings/ergo-wallet-wasm/src/lib.rs | 17 +++++++++++++++++ bindings/ergo-wallet-wasm/tests/transaction.rs | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index 7baf8a8c0..4cb0bc078 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -101,6 +101,22 @@ impl TxInputs { TxInputs(vec![]) } } +/// +/// Transaction data inputs, array of ErgoBoxCandidate +#[wasm_bindgen] +pub struct TxDataInputs(Vec); + +#[wasm_bindgen] +impl TxDataInputs { + /// parse ErgoBoxCandidate array from json + #[allow(clippy::boxed_local)] + pub fn from_boxes(_boxes: Box<[JsValue]>) -> TxDataInputs { + // box in boxes.into_iter() { + // let _box: chain::ErgoBoxCandidate = jbox.into_serde().unwrap(); + // } + TxDataInputs(vec![]) + } +} /// Transaction outputs, array of ErgoBoxCandidate #[wasm_bindgen] @@ -202,6 +218,7 @@ impl Transaction { #[wasm_bindgen] pub fn new_signed_transaction( _inputs: TxInputs, + _data_inputs: TxDataInputs, _outputs: TxOutputs, _send_change_to: Address, _sk: SecretKey, diff --git a/bindings/ergo-wallet-wasm/tests/transaction.rs b/bindings/ergo-wallet-wasm/tests/transaction.rs index bdd9de813..9b495ffa8 100644 --- a/bindings/ergo-wallet-wasm/tests/transaction.rs +++ b/bindings/ergo-wallet-wasm/tests/transaction.rs @@ -10,6 +10,7 @@ wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] fn test_signed_p2pk_transaction() { let tx_inputs = TxInputs::from_boxes(Box::new([])); + let tx_data_inputs = TxDataInputs::from_boxes(Box::new([])); let send_change_to = Address::from_testnet_str("").expect("failed"); let sk = SecretKey::parse("").expect("failed"); let recipient = Address::from_testnet_str("").expect("failed"); @@ -17,6 +18,6 @@ fn test_signed_p2pk_transaction() { let outbox = ErgoBoxCandidate::new(1, 0, Contract::pay_to_address(recipient)); let out_boxes = [outbox.to_json().expect("failed")]; let tx_outputs = TxOutputs::from_boxes(Box::new(out_boxes)); - let res = new_signed_transaction(tx_inputs, tx_outputs, send_change_to, sk); + let res = new_signed_transaction(tx_inputs, tx_data_inputs, tx_outputs, send_change_to, sk); assert!(res.is_err()); } From 126f2c3f49410797558c02ba7ddec4f77f485604 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sat, 13 Jun 2020 17:55:40 +0300 Subject: [PATCH 09/20] add ErgoStateContext and use it new_signed_transaction(); --- bindings/ergo-wallet-wasm/package.json | 2 +- bindings/ergo-wallet-wasm/src/lib.rs | 15 ++++++++++++++- .../ergo-wallet-wasm/tests/test_transaction.js | 10 ++++++---- bindings/ergo-wallet-wasm/tests/transaction.rs | 10 +++++++++- ergo-wallet/src/ergo_state_context.rs | 2 ++ ergo-wallet/src/lib.rs | 2 ++ 6 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 ergo-wallet/src/ergo_state_context.rs diff --git a/bindings/ergo-wallet-wasm/package.json b/bindings/ergo-wallet-wasm/package.json index 5f13c1b9d..0a17e5175 100644 --- a/bindings/ergo-wallet-wasm/package.json +++ b/bindings/ergo-wallet-wasm/package.json @@ -3,7 +3,7 @@ "build": "webpack", "serve": "wasm-pack build --target browser && webpack-dev-server", "test": "wasm-pack build --target nodejs && mocha --require @babel/register --require @babel/polyfill 'tests/test*.js'", - "doc": "jsdoc -c jsdoc.json pkg/sigma_tree_wasm.js README.md -d docs" + "doc": "jsdoc -c jsdoc.json pkg/ergo_wallet_wasm.js README.md -d docs" }, "devDependencies": { "@babel/core": "^7.6.4", diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index 4cb0bc078..59ecc1aa2 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -209,6 +209,18 @@ impl Transaction { } } +/// TBD +#[wasm_bindgen] +pub struct ErgoStateContext(ergo_wallet::ErgoStateContext); + +#[wasm_bindgen] +impl ErgoStateContext { + /// empty (dummy) context (for signing P2PK tx only) + pub fn empty() -> ErgoStateContext { + ErgoStateContext(ergo_wallet::ErgoStateContext()) + } +} + /// Create a signed transaction from: /// `inputs` - boxes [`ErgoBoxCandidate`] that will be spent /// `outputs` - boxes that will be created in this transaction @@ -217,6 +229,7 @@ impl Transaction { /// `sk` - secret key to sign the transaction (make proofs for inputs) #[wasm_bindgen] pub fn new_signed_transaction( + _state_context: ErgoStateContext, _inputs: TxInputs, _data_inputs: TxDataInputs, _outputs: TxOutputs, @@ -224,5 +237,5 @@ pub fn new_signed_transaction( _sk: SecretKey, ) -> Result { // not implemented, see https://github.com/ergoplatform/sigma-rust/issues/34 - Err(JsValue::from_str("Error!")) + Err(JsValue::from_str("Not yet implemented")) } diff --git a/bindings/ergo-wallet-wasm/tests/test_transaction.js b/bindings/ergo-wallet-wasm/tests/test_transaction.js index 3b3f3a590..fbbad1df5 100644 --- a/bindings/ergo-wallet-wasm/tests/test_transaction.js +++ b/bindings/ergo-wallet-wasm/tests/test_transaction.js @@ -1,10 +1,10 @@ import { expect } from 'chai'; -import {TxInputs, SecretKey, ErgoBoxCandidate, Contract, TxOutputs} from '../pkg/sigma_tree_wasm'; +import {TxInputs, TxDataInputs, SecretKey, ErgoBoxCandidate, Contract, TxOutputs, ErgoStateContext} from '../pkg/ergo_wallet_wasm'; -const sigma_rust = import('../pkg/sigma_tree_wasm'); +const sigma_rust = import('../pkg/ergo_wallet_wasm'); -it('new transaction', async () => { +it('new signed transaction', async () => { const { Address, new_signed_transaction, @@ -12,11 +12,13 @@ it('new transaction', async () => { const recipient = Address.from_testnet_str('test'); const tx_inputs = TxInputs.from_boxes([]); + const tx_data_inputs = TxDataInputs.from_boxes([]); const send_change_to = Address.from_testnet_str(''); const sk = SecretKey.parse(''); let outbox = new ErgoBoxCandidate(1, 0, Contract.pay_to_address(recipient)); let tx_outputs = TxOutputs.from_boxes([outbox]); - expect(() => new_signed_transaction(tx_inputs, tx_outputs, send_change_to, sk)).to.throw(); + let dummy_ctx = ErgoStateContext.empty(); + expect(() => new_signed_transaction(dummy_ctx, tx_inputs, tx_data_inputs, tx_outputs, send_change_to, sk)).to.throw("Not yet implemented"); }); diff --git a/bindings/ergo-wallet-wasm/tests/transaction.rs b/bindings/ergo-wallet-wasm/tests/transaction.rs index 9b495ffa8..1fbac8e89 100644 --- a/bindings/ergo-wallet-wasm/tests/transaction.rs +++ b/bindings/ergo-wallet-wasm/tests/transaction.rs @@ -18,6 +18,14 @@ fn test_signed_p2pk_transaction() { let outbox = ErgoBoxCandidate::new(1, 0, Contract::pay_to_address(recipient)); let out_boxes = [outbox.to_json().expect("failed")]; let tx_outputs = TxOutputs::from_boxes(Box::new(out_boxes)); - let res = new_signed_transaction(tx_inputs, tx_data_inputs, tx_outputs, send_change_to, sk); + let dummy_ctx = ErgoStateContext::empty(); + let res = new_signed_transaction( + dummy_ctx, + tx_inputs, + tx_data_inputs, + tx_outputs, + send_change_to, + sk, + ); assert!(res.is_err()); } diff --git a/ergo-wallet/src/ergo_state_context.rs b/ergo-wallet/src/ergo_state_context.rs new file mode 100644 index 000000000..d7fdff597 --- /dev/null +++ b/ergo-wallet/src/ergo_state_context.rs @@ -0,0 +1,2 @@ +/// TBD +pub struct ErgoStateContext(); diff --git a/ergo-wallet/src/lib.rs b/ergo-wallet/src/lib.rs index cf436bccf..c98c5d5b6 100644 --- a/ergo-wallet/src/lib.rs +++ b/ergo-wallet/src/lib.rs @@ -10,6 +10,8 @@ #![deny(unused_imports)] #![deny(missing_docs)] +mod ergo_state_context; mod secret_key; +pub use ergo_state_context::*; pub use secret_key::*; From 02da19972367e6d9e30343468f688a106b908488 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sun, 14 Jun 2020 17:52:01 +0300 Subject: [PATCH 10/20] draft ErgoStateContext building; --- bindings/ergo-wallet-c/src/lib.rs | 7 +++++++ bindings/ergo-wallet-c/src/misc_c.rs | 0 bindings/ergo-wallet-wasm/src/lib.rs | 4 ++-- .../ergo-wallet-wasm/tests/test_transaction.js | 2 +- bindings/ergo-wallet-wasm/tests/transaction.rs | 2 +- ergo-wallet/src/ergo_state_context.rs | 15 +++++++++++++++ 6 files changed, 26 insertions(+), 4 deletions(-) delete mode 100644 bindings/ergo-wallet-c/src/misc_c.rs diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index c3a62af1d..61b93182e 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -18,3 +18,10 @@ use std::os::raw::{c_int, c_longlong}; pub extern "C" fn add_numbers(x: c_int, y: c_int) -> c_longlong { x as i64 + y as i64 } + +// TODO: setup Xcode project and the build pipeline on CI + +// TODO Workflow: +// - parse boxes from JSON +// - make a tx (return opaque pointer?) +// - convert tx(opaque pointer) to JSON diff --git a/bindings/ergo-wallet-c/src/misc_c.rs b/bindings/ergo-wallet-c/src/misc_c.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index 59ecc1aa2..0dfd0af33 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -216,8 +216,8 @@ pub struct ErgoStateContext(ergo_wallet::ErgoStateContext); #[wasm_bindgen] impl ErgoStateContext { /// empty (dummy) context (for signing P2PK tx only) - pub fn empty() -> ErgoStateContext { - ErgoStateContext(ergo_wallet::ErgoStateContext()) + pub fn dummy() -> ErgoStateContext { + ErgoStateContext(ergo_wallet::ErgoStateContext::dummy()) } } diff --git a/bindings/ergo-wallet-wasm/tests/test_transaction.js b/bindings/ergo-wallet-wasm/tests/test_transaction.js index fbbad1df5..8a3012715 100644 --- a/bindings/ergo-wallet-wasm/tests/test_transaction.js +++ b/bindings/ergo-wallet-wasm/tests/test_transaction.js @@ -18,7 +18,7 @@ it('new signed transaction', async () => { let outbox = new ErgoBoxCandidate(1, 0, Contract.pay_to_address(recipient)); let tx_outputs = TxOutputs.from_boxes([outbox]); - let dummy_ctx = ErgoStateContext.empty(); + let dummy_ctx = ErgoStateContext.dummy(); expect(() => new_signed_transaction(dummy_ctx, tx_inputs, tx_data_inputs, tx_outputs, send_change_to, sk)).to.throw("Not yet implemented"); }); diff --git a/bindings/ergo-wallet-wasm/tests/transaction.rs b/bindings/ergo-wallet-wasm/tests/transaction.rs index 1fbac8e89..b1a3d726f 100644 --- a/bindings/ergo-wallet-wasm/tests/transaction.rs +++ b/bindings/ergo-wallet-wasm/tests/transaction.rs @@ -18,7 +18,7 @@ fn test_signed_p2pk_transaction() { let outbox = ErgoBoxCandidate::new(1, 0, Contract::pay_to_address(recipient)); let out_boxes = [outbox.to_json().expect("failed")]; let tx_outputs = TxOutputs::from_boxes(Box::new(out_boxes)); - let dummy_ctx = ErgoStateContext::empty(); + let dummy_ctx = ErgoStateContext::dummy(); let res = new_signed_transaction( dummy_ctx, tx_inputs, diff --git a/ergo-wallet/src/ergo_state_context.rs b/ergo-wallet/src/ergo_state_context.rs index d7fdff597..2cff90cad 100644 --- a/ergo-wallet/src/ergo_state_context.rs +++ b/ergo-wallet/src/ergo_state_context.rs @@ -1,2 +1,17 @@ /// TBD pub struct ErgoStateContext(); + +impl ErgoStateContext { + /// Dummy "empty" context + pub fn dummy() -> ErgoStateContext { + ErgoStateContext() + } + + /// build from last block headers from node REST API "blocks/lastHeaders/{count}" + pub fn from_last_headers(_json_str: &str) -> Result { + todo!() + } +} + +/// Errors on parsing and building from node REST API blocks/lastHeaders +pub enum ErgoStateContextError {} From 2b72d58eb0b503b63fca34f8f96e87e0ef418afd Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Sun, 14 Jun 2020 18:39:36 +0300 Subject: [PATCH 11/20] start drafting C API; --- bindings/ergo-wallet-c/Cargo.toml | 3 ++- bindings/ergo-wallet-c/h/sigma.h | 12 +++++++++++ bindings/ergo-wallet-c/src/lib.rs | 34 +++++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/bindings/ergo-wallet-c/Cargo.toml b/bindings/ergo-wallet-c/Cargo.toml index 9699f4a6a..8f1f5818f 100644 --- a/bindings/ergo-wallet-c/Cargo.toml +++ b/bindings/ergo-wallet-c/Cargo.toml @@ -11,7 +11,8 @@ crate-type = ["staticlib"] [dependencies] ffi_helpers = "0.2" -sigma-tree = { path = "../../sigma-tree", version = "0.1.0" } +sigma-tree = { path = "../../sigma-tree"} +ergo-wallet = { path = "../../ergo-wallet"} [build-dependencies] cbindgen = "0.14" diff --git a/bindings/ergo-wallet-c/h/sigma.h b/bindings/ergo-wallet-c/h/sigma.h index 1e3056818..9568a728c 100644 --- a/bindings/ergo-wallet-c/h/sigma.h +++ b/bindings/ergo-wallet-c/h/sigma.h @@ -6,7 +6,19 @@ #include +typedef ErgoStateContext *ErgoStateContextPtr; + +typedef Address *AddressPtr; + +typedef SecretKey *SecretKeyPtr; + /** * test */ long long add_numbers(int x, int y); + +ErrorPtr new_signed_transaction(ErgoStateContextPtr _state_context, + AddressPtr _send_change_to, + SecretKeyPtr _sk, + const uint8_t **transaction_out, + uintptr_t *len_out); diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index 61b93182e..ed87a43eb 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -9,7 +9,7 @@ #![deny(unused_imports)] #![deny(missing_docs)] -// use sigma_tree::chain; +use sigma_tree::chain; use std::os::raw::{c_int, c_longlong}; @@ -20,8 +20,34 @@ pub extern "C" fn add_numbers(x: c_int, y: c_int) -> c_longlong { } // TODO: setup Xcode project and the build pipeline on CI +// TODO: share code with future JNI bindings // TODO Workflow: -// - parse boxes from JSON -// - make a tx (return opaque pointer?) -// - convert tx(opaque pointer) to JSON +// - parse boxes from JSON and return bytes +// - make a tx (return bytes) +// - convert tx (bytes) to JSON + +pub type ErgoStateContextPtr = *mut ergo_wallet::ErgoStateContext; +// TODO wrap enum(TBD) into struct +pub type AddressPtr = *mut chain::Address; +pub type SecretKeyPtr = *mut ergo_wallet::SecretKey; + +// TODO: find a way to pass list of boxes? +// TODO: build outputs myself (no sane way to build them on the other side) +// TODO: make return error type + +#[no_mangle] +pub extern "C" fn new_signed_transaction( + _state_context: ErgoStateContextPtr, + // _inputs: TxInputsPtr, + // _data_inputs: TxDataInputs, + // _outputs: TxOutputs, + _send_change_to: AddressPtr, + _sk: SecretKeyPtr, + transaction_out: *mut *const u8, + len_out: *mut usize, +) -> ErrorPtr { + todo!() + // let r = wallet_vote_cast(wallet, settings, proposal, choice, transaction_out, len_out); + // r.into_c_api() +} From b981621493b9336f528e0e58d1222255e5b3934c Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 15 Jun 2020 16:07:06 +0300 Subject: [PATCH 12/20] draft the majority of ergo-wallet-c Rust API; --- bindings/ergo-wallet-c/h/sigma.h | 67 +++++++++++++--- bindings/ergo-wallet-c/src/error.rs | 10 +++ bindings/ergo-wallet-c/src/lib.rs | 120 ++++++++++++++++++++++------ 3 files changed, 162 insertions(+), 35 deletions(-) create mode 100644 bindings/ergo-wallet-c/src/error.rs diff --git a/bindings/ergo-wallet-c/h/sigma.h b/bindings/ergo-wallet-c/h/sigma.h index 9568a728c..ac80afb90 100644 --- a/bindings/ergo-wallet-c/h/sigma.h +++ b/bindings/ergo-wallet-c/h/sigma.h @@ -6,19 +6,66 @@ #include -typedef ErgoStateContext *ErgoStateContextPtr; +typedef struct Address Address; + +typedef struct DataInputBoxes DataInputBoxes; + +typedef struct ErgoBoxCandidate ErgoBoxCandidate; + +typedef struct Error Error; + +typedef struct OutputBoxes OutputBoxes; + +typedef struct Transaction Transaction; + +typedef struct UnspentInputBoxes UnspentInputBoxes; + +typedef Error *ErrorPtr; + +typedef Transaction *TransactionPtr; + +typedef ErgoBoxCandidate *ErgoBoxCandidatePtr; typedef Address *AddressPtr; +typedef ErgoStateContext *ErgoStateContextPtr; + +typedef UnspentInputBoxes *UnspentInputBoxesPtr; + +typedef DataInputBoxes *DataInputBoxesPtr; + +typedef OutputBoxes *OutputBoxesPtr; + typedef SecretKey *SecretKeyPtr; -/** - * test - */ -long long add_numbers(int x, int y); +ErrorPtr ergo_wallet_delete_signed_tx(TransactionPtr _transaction); + +ErrorPtr ergo_wallet_ergo_box_candidate_delete(ErgoBoxCandidatePtr _ergo_box_candidate); + +ErrorPtr ergo_wallet_ergo_box_candidate_new_pay_to_address(AddressPtr _recipient, + uint64_t _value, + uint32_t _creation_height, + ErgoBoxCandidatePtr *_ergo_box_candidate_out); + +ErrorPtr ergo_wallet_new_signed_tx(ErgoStateContextPtr _state_context, + UnspentInputBoxesPtr _unspent_input_boxes, + DataInputBoxesPtr _data_input_boxes, + OutputBoxesPtr _output_boxes, + AddressPtr _send_change_to, + uint64_t _min_change_value, + uint64_t _tx_fee_amount, + SecretKeyPtr _sk, + TransactionPtr *_transaction_out); + +ErrorPtr ergo_wallet_output_boxes_delete(OutputBoxesPtr _output_boxes); + +ErrorPtr ergo_wallet_output_boxes_new(ErgoBoxCandidatePtr _ergo_box_candidate, + OutputBoxesPtr *_output_boxes_out); + +ErrorPtr ergo_wallet_signed_tx_to_json(TransactionPtr _transaction, const char **_json_str_out); + +ErrorPtr ergo_wallet_unspent_input_boxes_delete(UnspentInputBoxesPtr _unspent_input_boxes); -ErrorPtr new_signed_transaction(ErgoStateContextPtr _state_context, - AddressPtr _send_change_to, - SecretKeyPtr _sk, - const uint8_t **transaction_out, - uintptr_t *len_out); +ErrorPtr ergo_wallet_unspent_input_boxes_from_json(const uint8_t *_json_str, + uintptr_t _json_str_len, + UnspentInputBoxesPtr *_unspent_input_boxes_out); diff --git a/bindings/ergo-wallet-c/src/error.rs b/bindings/ergo-wallet-c/src/error.rs new file mode 100644 index 000000000..945133a3d --- /dev/null +++ b/bindings/ergo-wallet-c/src/error.rs @@ -0,0 +1,10 @@ +use std::{error, result}; + +pub type Result = result::Result>; + +#[derive(Debug)] +pub struct Error { + details: Option>, +} + +pub type ErrorPtr = *mut Error; diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index ed87a43eb..043b75887 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -7,47 +7,117 @@ #![deny(unused_mut)] #![deny(dead_code)] #![deny(unused_imports)] -#![deny(missing_docs)] +// #![deny(missing_docs)] use sigma_tree::chain; -use std::os::raw::{c_int, c_longlong}; - -/// test -#[no_mangle] -pub extern "C" fn add_numbers(x: c_int, y: c_int) -> c_longlong { - x as i64 + y as i64 -} +use std::os::raw::c_char; // TODO: setup Xcode project and the build pipeline on CI // TODO: share code with future JNI bindings -// TODO Workflow: -// - parse boxes from JSON and return bytes -// - make a tx (return bytes) -// - convert tx (bytes) to JSON +mod error; +pub use error::*; + +pub struct Address(Box); pub type ErgoStateContextPtr = *mut ergo_wallet::ErgoStateContext; // TODO wrap enum(TBD) into struct -pub type AddressPtr = *mut chain::Address; +// TODO: make the same new/free functions as for UnspentInputBoxes +pub type AddressPtr = *mut Address; +// TODO: make the same new/free functions as for UnspentInputBoxes pub type SecretKeyPtr = *mut ergo_wallet::SecretKey; -// TODO: find a way to pass list of boxes? -// TODO: build outputs myself (no sane way to build them on the other side) -// TODO: make return error type +// TODO: sync changes to WASM API +// TODO: add docs +// TODO: extract into files/modules? + +pub struct ErgoBoxCandidate(chain::ErgoBoxCandidate); +pub type ErgoBoxCandidatePtr = *mut ErgoBoxCandidate; + +#[no_mangle] +pub extern "C" fn ergo_wallet_ergo_box_candidate_new_pay_to_address( + _recipient: AddressPtr, + _value: u64, + _creation_height: u32, + _ergo_box_candidate_out: *mut ErgoBoxCandidatePtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_ergo_box_candidate_delete( + _ergo_box_candidate: ErgoBoxCandidatePtr, +) -> ErrorPtr { + todo!() +} + +pub struct UnspentInputBoxes(Vec); +pub type UnspentInputBoxesPtr = *mut UnspentInputBoxes; + +#[no_mangle] +pub extern "C" fn ergo_wallet_unspent_input_boxes_from_json( + _json_str: *const u8, + _json_str_len: usize, + _unspent_input_boxes_out: *mut UnspentInputBoxesPtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_unspent_input_boxes_delete( + _unspent_input_boxes: UnspentInputBoxesPtr, +) -> ErrorPtr { + todo!() +} + +pub struct DataInputBoxes(Vec); +pub type DataInputBoxesPtr = *mut DataInputBoxes; + +pub struct OutputBoxes(Vec); +pub type OutputBoxesPtr = *mut OutputBoxes; + +#[no_mangle] +pub extern "C" fn ergo_wallet_output_boxes_new( + _ergo_box_candidate: ErgoBoxCandidatePtr, + _output_boxes_out: *mut OutputBoxesPtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_output_boxes_delete(_output_boxes: OutputBoxesPtr) -> ErrorPtr { + todo!() +} #[no_mangle] -pub extern "C" fn new_signed_transaction( - _state_context: ErgoStateContextPtr, - // _inputs: TxInputsPtr, - // _data_inputs: TxDataInputs, - // _outputs: TxOutputs, +pub extern "C" fn ergo_wallet_new_signed_tx( + _state_context: ErgoStateContextPtr, // can be null or make "empty" func? + _unspent_input_boxes: UnspentInputBoxesPtr, + _data_input_boxes: DataInputBoxesPtr, // can be null + _output_boxes: OutputBoxesPtr, _send_change_to: AddressPtr, + _min_change_value: u64, + _tx_fee_amount: u64, _sk: SecretKeyPtr, - transaction_out: *mut *const u8, - len_out: *mut usize, + _transaction_out: *mut TransactionPtr, +) -> ErrorPtr { + todo!() +} + +pub struct Transaction(chain::Transaction); +pub type TransactionPtr = *mut Transaction; + +#[no_mangle] +pub extern "C" fn ergo_wallet_delete_signed_tx(_transaction: TransactionPtr) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_signed_tx_to_json( + _transaction: TransactionPtr, + _json_str_out: *mut *const c_char, ) -> ErrorPtr { todo!() - // let r = wallet_vote_cast(wallet, settings, proposal, choice, transaction_out, len_out); - // r.into_c_api() } + From 3bb784bbd2114a883def2beff285a8d521fd70dc Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 15 Jun 2020 18:51:15 +0300 Subject: [PATCH 13/20] draft ErgoWallet iOS framework; --- .editorconfig | 5 +++++ .gitignore | 6 ++++++ .travis.yml | 4 ++++ bindings/ergo-wallet-c/build.rs | 2 +- .../h/{sigma.h => ergo_wallet.h} | 7 +++++-- bindings/ergo-wallet-c/src/lib.rs | 9 +++++---- .../ergo-wallet-ios/Config/Release.xcconfig | 11 ++++++++++ bindings/ergo-wallet-ios/Package.swift | 20 +++++++++++++++++++ .../Sources/ErgoWallet/ErgoWallet.swift | 14 +++++++++++++ .../Sources/ErgoWalletC/module.modulemap | 4 ++++ .../Sources/ErgoWalletC/shim.h | 6 ++++++ 11 files changed, 81 insertions(+), 7 deletions(-) rename bindings/ergo-wallet-c/h/{sigma.h => ergo_wallet.h} (93%) create mode 100644 bindings/ergo-wallet-ios/Config/Release.xcconfig create mode 100644 bindings/ergo-wallet-ios/Package.swift create mode 100644 bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift create mode 100644 bindings/ergo-wallet-ios/Sources/ErgoWalletC/module.modulemap create mode 100644 bindings/ergo-wallet-ios/Sources/ErgoWalletC/shim.h diff --git a/.editorconfig b/.editorconfig index be000868e..d80cee0b3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,8 @@ trim_trailing_whitespace = true [*.{md, markdown, eex}] trim_trailing_whitespace = false +[*.swift] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 diff --git a/.gitignore b/.gitignore index b21b12eeb..4dd183aff 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,9 @@ wasm-pack.log **/dist **/docs package-lock.json + +bindings/ergo-wallet-ios/.build +bindings/ergo-wallet-ios/build +bindings/ergo-wallet-ios/Packages +bindings/ergo-wallet-ios/*.xcodeproj +bindings/ergo-wallet-ios/xcuserdata/ diff --git a/.travis.yml b/.travis.yml index 873852402..8e99cb3bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -95,7 +95,11 @@ matrix: - cargo install cargo-lipo - cargo install cbindgen script: + - cd bindings/ergo-wallet-ios - cargo lipo --release --targets=aarch64-apple-ios,x86_64-apple-ios + - xcodebuild -project ./ErgoWallet.xcodeproj -xcconfig ./Config/Release.xcconfig -sdk iphoneos + - xcodebuild -project ./ErgoWallet.xcodeproj -xcconfig ./Config/Release.xcconfig -sdk iphonesimulator + cache: cargo # But don't cache the cargo registry diff --git a/bindings/ergo-wallet-c/build.rs b/bindings/ergo-wallet-c/build.rs index d8a74dc42..56e9b6bf8 100644 --- a/bindings/ergo-wallet-c/build.rs +++ b/bindings/ergo-wallet-c/build.rs @@ -11,5 +11,5 @@ fn main() { .with_config(config) .generate() .expect("Unable to generate bindings") - .write_to_file("h/sigma.h"); + .write_to_file("h/ergo_wallet.h"); } diff --git a/bindings/ergo-wallet-c/h/sigma.h b/bindings/ergo-wallet-c/h/ergo_wallet.h similarity index 93% rename from bindings/ergo-wallet-c/h/sigma.h rename to bindings/ergo-wallet-c/h/ergo_wallet.h index ac80afb90..ca54b5d3f 100644 --- a/bindings/ergo-wallet-c/h/sigma.h +++ b/bindings/ergo-wallet-c/h/ergo_wallet.h @@ -12,10 +12,14 @@ typedef struct DataInputBoxes DataInputBoxes; typedef struct ErgoBoxCandidate ErgoBoxCandidate; +typedef struct ErgoStateContext ErgoStateContext; + typedef struct Error Error; typedef struct OutputBoxes OutputBoxes; +typedef struct SecretKey SecretKey; + typedef struct Transaction Transaction; typedef struct UnspentInputBoxes UnspentInputBoxes; @@ -66,6 +70,5 @@ ErrorPtr ergo_wallet_signed_tx_to_json(TransactionPtr _transaction, const char * ErrorPtr ergo_wallet_unspent_input_boxes_delete(UnspentInputBoxesPtr _unspent_input_boxes); -ErrorPtr ergo_wallet_unspent_input_boxes_from_json(const uint8_t *_json_str, - uintptr_t _json_str_len, +ErrorPtr ergo_wallet_unspent_input_boxes_from_json(const char *_json_str, UnspentInputBoxesPtr *_unspent_input_boxes_out); diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index 043b75887..24e50b171 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -20,13 +20,15 @@ mod error; pub use error::*; pub struct Address(Box); +pub struct ErgoStateContext(ergo_wallet::ErgoStateContext); +pub struct SecretKey(ergo_wallet::SecretKey); -pub type ErgoStateContextPtr = *mut ergo_wallet::ErgoStateContext; +pub type ErgoStateContextPtr = *mut ErgoStateContext; // TODO wrap enum(TBD) into struct // TODO: make the same new/free functions as for UnspentInputBoxes pub type AddressPtr = *mut Address; // TODO: make the same new/free functions as for UnspentInputBoxes -pub type SecretKeyPtr = *mut ergo_wallet::SecretKey; +pub type SecretKeyPtr = *mut SecretKey; // TODO: sync changes to WASM API // TODO: add docs @@ -57,8 +59,7 @@ pub type UnspentInputBoxesPtr = *mut UnspentInputBoxes; #[no_mangle] pub extern "C" fn ergo_wallet_unspent_input_boxes_from_json( - _json_str: *const u8, - _json_str_len: usize, + _json_str: *const c_char, _unspent_input_boxes_out: *mut UnspentInputBoxesPtr, ) -> ErrorPtr { todo!() diff --git a/bindings/ergo-wallet-ios/Config/Release.xcconfig b/bindings/ergo-wallet-ios/Config/Release.xcconfig new file mode 100644 index 000000000..fc3b2594d --- /dev/null +++ b/bindings/ergo-wallet-ios/Config/Release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION = Release +TARGET_NAME = ErgoWallet +SUPPORTED_PLATFORMS = iphonesimulator iphoneos +VALID_ARCHS = arm64 x86_64 +ENABLE_BITCODE = NO +BUILD_LIBRARY_FOR_DISTRIBUTION = YES +HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/../ergo-wallet-c/h +OTHER_LDFLAGS = $(inherited) -L"$(SRCROOT)/../../target/universal/release" -lergo_wallet_c +PRODUCT_BUNDLE_IDENTIFIER = org.ergoplatform.wallet +FRAMEWORK_VERSION = 0.1.0-pre1 + diff --git a/bindings/ergo-wallet-ios/Package.swift b/bindings/ergo-wallet-ios/Package.swift new file mode 100644 index 000000000..2d3bead78 --- /dev/null +++ b/bindings/ergo-wallet-ios/Package.swift @@ -0,0 +1,20 @@ +// swift-tools-version:5.2 + +import PackageDescription + +let package = Package( + name: "ErgoWallet", + products: [ + .library( + name: "ErgoWallet", + targets: ["ErgoWallet"] + ) + ], + targets: [ + .systemLibrary(name: "ErgoWalletC"), + .target( + name: "ErgoWallet", + dependencies: ["ErgoWalletC"] + ), + ] +) diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift new file mode 100644 index 000000000..30362a4be --- /dev/null +++ b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift @@ -0,0 +1,14 @@ +import Foundation +import ErgoWalletC + +struct UnspentInputBoxes { + private init() {} + static func from_json(json: String) throws -> UnspentInputBoxesPtr { + var unspentInputBoxesPtr: UnspentInputBoxesPtr? + let _ = json.withCString { cs in + ergo_wallet_unspent_input_boxes_from_json(cs, &unspentInputBoxesPtr) + } + return unspentInputBoxesPtr! + } +} + diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWalletC/module.modulemap b/bindings/ergo-wallet-ios/Sources/ErgoWalletC/module.modulemap new file mode 100644 index 000000000..53c45c5a8 --- /dev/null +++ b/bindings/ergo-wallet-ios/Sources/ErgoWalletC/module.modulemap @@ -0,0 +1,4 @@ +module ErgoWalletC { + umbrella header "shim.h" + export * +} diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWalletC/shim.h b/bindings/ergo-wallet-ios/Sources/ErgoWalletC/shim.h new file mode 100644 index 000000000..207f86805 --- /dev/null +++ b/bindings/ergo-wallet-ios/Sources/ErgoWalletC/shim.h @@ -0,0 +1,6 @@ +#ifndef ERGO_WALLET_SHIM_H_ +#define ERGO_WALLET_SHIM_H_ + +#include "ergo_wallet.h" + +#endif /* ERGO_WALLET_SHIM_H_ */ From 62df130d4c52b3f2fb64fbd2e801d80c6b528b6b Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 16 Jun 2020 08:58:59 +0300 Subject: [PATCH 14/20] add Transaction in Swift wrapper; add Xcode project generation step on CI; --- .travis.yml | 1 + bindings/ergo-wallet-c/h/ergo_wallet.h | 2 + bindings/ergo-wallet-c/src/lib.rs | 11 ++++- .../Sources/ErgoWallet/ErgoWallet.swift | 45 +++++++++++++++++-- 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8e99cb3bd..c767768cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -97,6 +97,7 @@ matrix: script: - cd bindings/ergo-wallet-ios - cargo lipo --release --targets=aarch64-apple-ios,x86_64-apple-ios + - swift package generate-xcodeproj - xcodebuild -project ./ErgoWallet.xcodeproj -xcconfig ./Config/Release.xcconfig -sdk iphoneos - xcodebuild -project ./ErgoWallet.xcodeproj -xcconfig ./Config/Release.xcconfig -sdk iphonesimulator diff --git a/bindings/ergo-wallet-c/h/ergo_wallet.h b/bindings/ergo-wallet-c/h/ergo_wallet.h index ca54b5d3f..0289e33cf 100644 --- a/bindings/ergo-wallet-c/h/ergo_wallet.h +++ b/bindings/ergo-wallet-c/h/ergo_wallet.h @@ -44,6 +44,8 @@ typedef SecretKey *SecretKeyPtr; ErrorPtr ergo_wallet_delete_signed_tx(TransactionPtr _transaction); +void ergo_wallet_delete_string(char *ptr); + ErrorPtr ergo_wallet_ergo_box_candidate_delete(ErgoBoxCandidatePtr _ergo_box_candidate); ErrorPtr ergo_wallet_ergo_box_candidate_new_pay_to_address(AddressPtr _recipient, diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index 24e50b171..eee2fd1f8 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -11,9 +11,9 @@ use sigma_tree::chain; -use std::os::raw::c_char; +use std::{ffi::CString, os::raw::c_char}; -// TODO: setup Xcode project and the build pipeline on CI +// TODO: finish ErgoWallet Swift wrapper // TODO: share code with future JNI bindings mod error; @@ -122,3 +122,10 @@ pub extern "C" fn ergo_wallet_signed_tx_to_json( todo!() } +#[no_mangle] +pub unsafe extern "C" fn ergo_wallet_delete_string(ptr: *mut c_char) { + if !ptr.is_null() { + let cstring = CString::from_raw(ptr); + std::mem::drop(cstring) + } +} diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift index 30362a4be..2c695697c 100644 --- a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift +++ b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift @@ -1,14 +1,53 @@ import Foundation import ErgoWalletC -struct UnspentInputBoxes { - private init() {} - static func from_json(json: String) throws -> UnspentInputBoxesPtr { +class UnspentInputBoxes { + private var pointer: UnspentInputBoxesPtr + + init(withJson json: String) throws { + self.pointer = try UnspentInputBoxes.from_json(json: json) + } + + private static func from_json(json: String) throws -> UnspentInputBoxesPtr { var unspentInputBoxesPtr: UnspentInputBoxesPtr? + // TODO: handle error let _ = json.withCString { cs in ergo_wallet_unspent_input_boxes_from_json(cs, &unspentInputBoxesPtr) } return unspentInputBoxesPtr! } + + deinit { + ergo_wallet_unspent_input_boxes_delete(self.pointer) + } +} + +class Transaction { + private var pointer: TransactionPtr + + internal init(withRawPointer pointer: TransactionPtr) { + self.pointer = pointer + } + + func toJson() throws -> String { + var cStr: UnsafePointer? + let _ = try ergo_wallet_signed_tx_to_json(self.pointer, &cStr) + // TODO: process error + let str = String(cString: cStr!) + ergo_wallet_delete_string(UnsafeMutablePointer(mutating: cStr)) + return str + } + + deinit { + ergo_wallet_delete_signed_tx(self.pointer) + } +} + +struct Wallet { + + // static func new_signed_tx(unspentInputBoxes: UnspentInputBoxes) throws -> Transaction { + + + // } } From b4b513e1fc12191a9e0785535bbade67d32820ca Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 16 Jun 2020 15:19:40 +0300 Subject: [PATCH 15/20] add error handling in Swift wrapper; --- bindings/ergo-wallet-c/h/ergo_wallet.h | 4 +++ bindings/ergo-wallet-c/src/error.rs | 11 ++++++-- bindings/ergo-wallet-c/src/lib.rs | 17 ++++++++++++ .../Sources/ErgoWallet/ErgoWallet.swift | 27 ++++++++++++++----- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/bindings/ergo-wallet-c/h/ergo_wallet.h b/bindings/ergo-wallet-c/h/ergo_wallet.h index 0289e33cf..2ae775bfc 100644 --- a/bindings/ergo-wallet-c/h/ergo_wallet.h +++ b/bindings/ergo-wallet-c/h/ergo_wallet.h @@ -42,6 +42,8 @@ typedef OutputBoxes *OutputBoxesPtr; typedef SecretKey *SecretKeyPtr; +void ergo_wallet_delete_error(ErrorPtr error); + ErrorPtr ergo_wallet_delete_signed_tx(TransactionPtr _transaction); void ergo_wallet_delete_string(char *ptr); @@ -53,6 +55,8 @@ ErrorPtr ergo_wallet_ergo_box_candidate_new_pay_to_address(AddressPtr _recipient uint32_t _creation_height, ErgoBoxCandidatePtr *_ergo_box_candidate_out); +char *ergo_wallet_error_to_string(ErrorPtr error); + ErrorPtr ergo_wallet_new_signed_tx(ErgoStateContextPtr _state_context, UnspentInputBoxesPtr _unspent_input_boxes, DataInputBoxesPtr _data_input_boxes, diff --git a/bindings/ergo-wallet-c/src/error.rs b/bindings/ergo-wallet-c/src/error.rs index 945133a3d..4f04e6db8 100644 --- a/bindings/ergo-wallet-c/src/error.rs +++ b/bindings/ergo-wallet-c/src/error.rs @@ -1,10 +1,17 @@ -use std::{error, result}; +use std::{error, fmt, result}; pub type Result = result::Result>; #[derive(Debug)] pub struct Error { - details: Option>, + details: Box, } pub type ErrorPtr = *mut Error; + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.details.as_ref(), f) + } +} + diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index eee2fd1f8..ebf9a1ac7 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -129,3 +129,20 @@ pub unsafe extern "C" fn ergo_wallet_delete_string(ptr: *mut c_char) { std::mem::drop(cstring) } } + +#[no_mangle] +pub extern "C" fn ergo_wallet_delete_error(error: ErrorPtr) { + if !error.is_null() { + let boxed = unsafe { Box::from_raw(error) }; + std::mem::drop(boxed); + } +} + +#[no_mangle] +pub unsafe extern "C" fn ergo_wallet_error_to_string(error: ErrorPtr) -> *mut c_char { + if let Some(error) = error.as_ref() { + CString::new(error.to_string()).unwrap().into_raw() + } else { + CString::new(b"success".to_vec()).unwrap().into_raw() + } +} diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift index 2c695697c..14a8b3a3b 100644 --- a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift +++ b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift @@ -1,6 +1,10 @@ import Foundation import ErgoWalletC +enum WalletError: Error { + case walletCError(reason: String) +} + class UnspentInputBoxes { private var pointer: UnspentInputBoxesPtr @@ -10,10 +14,10 @@ class UnspentInputBoxes { private static func from_json(json: String) throws -> UnspentInputBoxesPtr { var unspentInputBoxesPtr: UnspentInputBoxesPtr? - // TODO: handle error - let _ = json.withCString { cs in + let error = json.withCString { cs in ergo_wallet_unspent_input_boxes_from_json(cs, &unspentInputBoxesPtr) } + try checkError(error) return unspentInputBoxesPtr! } @@ -22,6 +26,18 @@ class UnspentInputBoxes { } } +private func checkError(_ error: ErrorPtr?) throws { + if error == nil { + return + } + + let cStringReason = ergo_wallet_error_to_string(error) + let reason = String(cString: cStringReason!) + ergo_wallet_delete_string(cStringReason) + ergo_wallet_delete_error(error) + throw WalletError.walletCError(reason: reason) +} + class Transaction { private var pointer: TransactionPtr @@ -31,8 +47,8 @@ class Transaction { func toJson() throws -> String { var cStr: UnsafePointer? - let _ = try ergo_wallet_signed_tx_to_json(self.pointer, &cStr) - // TODO: process error + let error = try ergo_wallet_signed_tx_to_json(self.pointer, &cStr) + try checkError(error) let str = String(cString: cStr!) ergo_wallet_delete_string(UnsafeMutablePointer(mutating: cStr)) return str @@ -46,8 +62,7 @@ class Transaction { struct Wallet { // static func new_signed_tx(unspentInputBoxes: UnspentInputBoxes) throws -> Transaction { - - // } + } From 57bc85a2c68608befd8025a42202d72a20f0b6ae Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 16 Jun 2020 17:40:58 +0300 Subject: [PATCH 16/20] finish Swift wrapper; --- bindings/ergo-wallet-c/h/ergo_wallet.h | 18 ++- bindings/ergo-wallet-c/src/lib.rs | 59 ++++++-- .../Sources/ErgoWallet/ErgoWallet.swift | 129 +++++++++++++++++- 3 files changed, 189 insertions(+), 17 deletions(-) diff --git a/bindings/ergo-wallet-c/h/ergo_wallet.h b/bindings/ergo-wallet-c/h/ergo_wallet.h index 2ae775bfc..ddd5253cd 100644 --- a/bindings/ergo-wallet-c/h/ergo_wallet.h +++ b/bindings/ergo-wallet-c/h/ergo_wallet.h @@ -26,12 +26,12 @@ typedef struct UnspentInputBoxes UnspentInputBoxes; typedef Error *ErrorPtr; +typedef Address *AddressPtr; + typedef Transaction *TransactionPtr; typedef ErgoBoxCandidate *ErgoBoxCandidatePtr; -typedef Address *AddressPtr; - typedef ErgoStateContext *ErgoStateContextPtr; typedef UnspentInputBoxes *UnspentInputBoxesPtr; @@ -42,6 +42,10 @@ typedef OutputBoxes *OutputBoxesPtr; typedef SecretKey *SecretKeyPtr; +ErrorPtr ergo_wallet_address_delete(AddressPtr _address); + +ErrorPtr ergo_wallet_address_from_testnet(const char *_address_str, AddressPtr *_address_out); + void ergo_wallet_delete_error(ErrorPtr error); ErrorPtr ergo_wallet_delete_signed_tx(TransactionPtr _transaction); @@ -55,6 +59,11 @@ ErrorPtr ergo_wallet_ergo_box_candidate_new_pay_to_address(AddressPtr _recipient uint32_t _creation_height, ErgoBoxCandidatePtr *_ergo_box_candidate_out); +ErrorPtr ergo_wallet_ergo_state_context_delete(ErgoStateContextPtr _ergo_state_context); + +ErrorPtr ergo_wallet_ergo_state_context_from_json(const char *_json_str, + ErgoStateContextPtr *_ergo_state_context_out); + char *ergo_wallet_error_to_string(ErrorPtr error); ErrorPtr ergo_wallet_new_signed_tx(ErgoStateContextPtr _state_context, @@ -72,6 +81,11 @@ ErrorPtr ergo_wallet_output_boxes_delete(OutputBoxesPtr _output_boxes); ErrorPtr ergo_wallet_output_boxes_new(ErgoBoxCandidatePtr _ergo_box_candidate, OutputBoxesPtr *_output_boxes_out); +ErrorPtr ergo_wallet_secret_key_delete(SecretKeyPtr _secret_key); + +ErrorPtr ergo_wallet_secret_key_parse_str(const char *_secret_key_str, + SecretKeyPtr *_secret_key_out); + ErrorPtr ergo_wallet_signed_tx_to_json(TransactionPtr _transaction, const char **_json_str_out); ErrorPtr ergo_wallet_unspent_input_boxes_delete(UnspentInputBoxesPtr _unspent_input_boxes); diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index ebf9a1ac7..a46f0ba43 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -13,26 +13,47 @@ use sigma_tree::chain; use std::{ffi::CString, os::raw::c_char}; -// TODO: finish ErgoWallet Swift wrapper +// TODO: sync changes to WASM API // TODO: share code with future JNI bindings +// TODO: add docs +// TODO: extract into files/modules? mod error; pub use error::*; -pub struct Address(Box); pub struct ErgoStateContext(ergo_wallet::ErgoStateContext); -pub struct SecretKey(ergo_wallet::SecretKey); - pub type ErgoStateContextPtr = *mut ErgoStateContext; -// TODO wrap enum(TBD) into struct -// TODO: make the same new/free functions as for UnspentInputBoxes -pub type AddressPtr = *mut Address; -// TODO: make the same new/free functions as for UnspentInputBoxes + +#[no_mangle] +pub unsafe extern "C" fn ergo_wallet_ergo_state_context_from_json( + _json_str: *const c_char, + _ergo_state_context_out: *mut ErgoStateContextPtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub unsafe extern "C" fn ergo_wallet_ergo_state_context_delete( + _ergo_state_context: ErgoStateContextPtr, +) -> ErrorPtr { + todo!() +} + +pub struct SecretKey(ergo_wallet::SecretKey); pub type SecretKeyPtr = *mut SecretKey; -// TODO: sync changes to WASM API -// TODO: add docs -// TODO: extract into files/modules? +#[no_mangle] +pub extern "C" fn ergo_wallet_secret_key_parse_str( + _secret_key_str: *const c_char, + _secret_key_out: *mut SecretKeyPtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_secret_key_delete(_secret_key: SecretKeyPtr) -> ErrorPtr { + todo!() +} pub struct ErgoBoxCandidate(chain::ErgoBoxCandidate); pub type ErgoBoxCandidatePtr = *mut ErgoBoxCandidate; @@ -54,6 +75,22 @@ pub extern "C" fn ergo_wallet_ergo_box_candidate_delete( todo!() } +pub struct Address(Box); +pub type AddressPtr = *mut Address; + +#[no_mangle] +pub extern "C" fn ergo_wallet_address_from_testnet( + _address_str: *const c_char, + _address_out: *mut AddressPtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_address_delete(_address: AddressPtr) -> ErrorPtr { + todo!() +} + pub struct UnspentInputBoxes(Vec); pub type UnspentInputBoxesPtr = *mut UnspentInputBoxes; diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift index 14a8b3a3b..6005b3acc 100644 --- a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift +++ b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift @@ -1,12 +1,14 @@ import Foundation import ErgoWalletC +// TODO: extract into files + enum WalletError: Error { case walletCError(reason: String) } class UnspentInputBoxes { - private var pointer: UnspentInputBoxesPtr + internal var pointer: UnspentInputBoxesPtr init(withJson json: String) throws { self.pointer = try UnspentInputBoxes.from_json(json: json) @@ -47,7 +49,7 @@ class Transaction { func toJson() throws -> String { var cStr: UnsafePointer? - let error = try ergo_wallet_signed_tx_to_json(self.pointer, &cStr) + let error = ergo_wallet_signed_tx_to_json(self.pointer, &cStr) try checkError(error) let str = String(cString: cStr!) ergo_wallet_delete_string(UnsafeMutablePointer(mutating: cStr)) @@ -59,10 +61,129 @@ class Transaction { } } +class ErgoStateContext { + internal var pointer: ErgoStateContextPtr + + init(withJson json: String) throws { + self.pointer = try ErgoStateContext.fromJson(json: json) + } + + private static func fromJson(json: String) throws -> ErgoStateContextPtr { + var ergoStateContextPtr: ErgoStateContextPtr? + let error = json.withCString { cs in + ergo_wallet_ergo_state_context_from_json(cs, &ergoStateContextPtr) + } + try checkError(error) + return ergoStateContextPtr! + } + + deinit { + ergo_wallet_ergo_state_context_delete(self.pointer) + } +} + +class Address { + internal var pointer: AddressPtr + + init(withTestnetAddress addressStr: String) throws { + self.pointer = try Address.fromTestnetAddress(addressStr: addressStr) + } + + private static func fromTestnetAddress(addressStr: String) throws -> AddressPtr { + var ptr: AddressPtr? + let error = addressStr.withCString { cs in + ergo_wallet_address_from_testnet(cs, &ptr) + } + try checkError(error) + return ptr! + } + + deinit { + ergo_wallet_address_delete(self.pointer) + } +} + +class ErgoBoxCandidate { + internal var pointer: ErgoBoxCandidatePtr + + internal init(withRawPointer pointer: ErgoBoxCandidatePtr) { + self.pointer = pointer + } + + static func payToAddress(recipient: Address, + value: UInt64, creationHeight: UInt32) throws -> ErgoBoxCandidate { + var ergoBoxCandidatePtr: ErgoBoxCandidatePtr? + let error = ergo_wallet_ergo_box_candidate_new_pay_to_address(recipient.pointer, + value, + creationHeight, + &ergoBoxCandidatePtr) + try checkError(error) + return ErgoBoxCandidate(withRawPointer: ergoBoxCandidatePtr!) + } + + deinit { + ergo_wallet_ergo_box_candidate_delete(self.pointer) + } +} + +class OutputBoxes { + internal var pointer: OutputBoxesPtr + + init(box: ErgoBoxCandidate) throws { + var ptr: OutputBoxesPtr? + let error = ergo_wallet_output_boxes_new(box.pointer, &ptr) + try checkError(error) + self.pointer = ptr! + } + + deinit { + ergo_wallet_unspent_input_boxes_delete(self.pointer) + } +} + +class SecretKey { + internal var pointer: SecretKeyPtr + + init(withString secretKeyStr: String) throws { + self.pointer = try SecretKey.fromString(secretKeyStr: secretKeyStr) + } + + private static func fromString(secretKeyStr: String) throws -> SecretKeyPtr { + var ptr: SecretKeyPtr? + let error = secretKeyStr.withCString { cs in + ergo_wallet_secret_key_parse_str(cs, &ptr) + } + try checkError(error) + return ptr! + } + + deinit { + ergo_wallet_secret_key_delete(self.pointer) + } +} + struct Wallet { - // static func new_signed_tx(unspentInputBoxes: UnspentInputBoxes) throws -> Transaction { - // } + static func new_signed_tx(ergoStateContext: ErgoStateContext, + unspentInputBoxes: UnspentInputBoxes, + outputBoxes: OutputBoxes, + sendChangeTo: Address, + minChangeValue: UInt64, + txFeeAmount: UInt64, + secretKey: SecretKey) throws -> Transaction { + var transactionPtr: TransactionPtr? + let error = ergo_wallet_new_signed_tx(ergoStateContext.pointer, + unspentInputBoxes.pointer, + nil, // data input boxes + outputBoxes.pointer, + sendChangeTo.pointer, + minChangeValue, + txFeeAmount, + secretKey.pointer, + &transactionPtr) + try checkError(error) + return Transaction(withRawPointer: transactionPtr!) + } } From 25c83d40fdbab8043a4851148833044571667f11 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 16 Jun 2020 17:50:00 +0300 Subject: [PATCH 17/20] rename UnspentInputBoxes to UnspentBoxes; --- bindings/ergo-wallet-c/h/ergo_wallet.h | 12 +++++----- bindings/ergo-wallet-c/src/lib.rs | 14 +++++------- .../Sources/ErgoWallet/ErgoWallet.swift | 22 +++++++++---------- bindings/ergo-wallet-wasm/src/lib.rs | 13 ++++++----- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/bindings/ergo-wallet-c/h/ergo_wallet.h b/bindings/ergo-wallet-c/h/ergo_wallet.h index ddd5253cd..3d4ebc8da 100644 --- a/bindings/ergo-wallet-c/h/ergo_wallet.h +++ b/bindings/ergo-wallet-c/h/ergo_wallet.h @@ -22,7 +22,7 @@ typedef struct SecretKey SecretKey; typedef struct Transaction Transaction; -typedef struct UnspentInputBoxes UnspentInputBoxes; +typedef struct UnspentBoxes UnspentBoxes; typedef Error *ErrorPtr; @@ -34,7 +34,7 @@ typedef ErgoBoxCandidate *ErgoBoxCandidatePtr; typedef ErgoStateContext *ErgoStateContextPtr; -typedef UnspentInputBoxes *UnspentInputBoxesPtr; +typedef UnspentBoxes *UnspentBoxesPtr; typedef DataInputBoxes *DataInputBoxesPtr; @@ -67,7 +67,7 @@ ErrorPtr ergo_wallet_ergo_state_context_from_json(const char *_json_str, char *ergo_wallet_error_to_string(ErrorPtr error); ErrorPtr ergo_wallet_new_signed_tx(ErgoStateContextPtr _state_context, - UnspentInputBoxesPtr _unspent_input_boxes, + UnspentBoxesPtr _unspent_boxes, DataInputBoxesPtr _data_input_boxes, OutputBoxesPtr _output_boxes, AddressPtr _send_change_to, @@ -88,7 +88,7 @@ ErrorPtr ergo_wallet_secret_key_parse_str(const char *_secret_key_str, ErrorPtr ergo_wallet_signed_tx_to_json(TransactionPtr _transaction, const char **_json_str_out); -ErrorPtr ergo_wallet_unspent_input_boxes_delete(UnspentInputBoxesPtr _unspent_input_boxes); +ErrorPtr ergo_wallet_unspent_boxes_delete(UnspentBoxesPtr _unspent_boxes); -ErrorPtr ergo_wallet_unspent_input_boxes_from_json(const char *_json_str, - UnspentInputBoxesPtr *_unspent_input_boxes_out); +ErrorPtr ergo_wallet_unspent_boxes_from_json(const char *_json_str, + UnspentBoxesPtr *_unspent_boxes_out); diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index a46f0ba43..08bb47229 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -91,21 +91,19 @@ pub extern "C" fn ergo_wallet_address_delete(_address: AddressPtr) -> ErrorPtr { todo!() } -pub struct UnspentInputBoxes(Vec); -pub type UnspentInputBoxesPtr = *mut UnspentInputBoxes; +pub struct UnspentBoxes(Vec); +pub type UnspentBoxesPtr = *mut UnspentBoxes; #[no_mangle] -pub extern "C" fn ergo_wallet_unspent_input_boxes_from_json( +pub extern "C" fn ergo_wallet_unspent_boxes_from_json( _json_str: *const c_char, - _unspent_input_boxes_out: *mut UnspentInputBoxesPtr, + _unspent_boxes_out: *mut UnspentBoxesPtr, ) -> ErrorPtr { todo!() } #[no_mangle] -pub extern "C" fn ergo_wallet_unspent_input_boxes_delete( - _unspent_input_boxes: UnspentInputBoxesPtr, -) -> ErrorPtr { +pub extern "C" fn ergo_wallet_unspent_boxes_delete(_unspent_boxes: UnspentBoxesPtr) -> ErrorPtr { todo!() } @@ -131,7 +129,7 @@ pub extern "C" fn ergo_wallet_output_boxes_delete(_output_boxes: OutputBoxesPtr) #[no_mangle] pub extern "C" fn ergo_wallet_new_signed_tx( _state_context: ErgoStateContextPtr, // can be null or make "empty" func? - _unspent_input_boxes: UnspentInputBoxesPtr, + _unspent_boxes: UnspentBoxesPtr, _data_input_boxes: DataInputBoxesPtr, // can be null _output_boxes: OutputBoxesPtr, _send_change_to: AddressPtr, diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift index 6005b3acc..e633efecb 100644 --- a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift +++ b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift @@ -7,24 +7,24 @@ enum WalletError: Error { case walletCError(reason: String) } -class UnspentInputBoxes { - internal var pointer: UnspentInputBoxesPtr +class UnspentBoxes { + internal var pointer: UnspentBoxesPtr init(withJson json: String) throws { - self.pointer = try UnspentInputBoxes.from_json(json: json) + self.pointer = try UnspentBoxes.from_json(json: json) } - private static func from_json(json: String) throws -> UnspentInputBoxesPtr { - var unspentInputBoxesPtr: UnspentInputBoxesPtr? + private static func from_json(json: String) throws -> UnspentBoxesPtr { + var unspentBoxesPtr: UnspentBoxesPtr? let error = json.withCString { cs in - ergo_wallet_unspent_input_boxes_from_json(cs, &unspentInputBoxesPtr) + ergo_wallet_unspent_boxes_from_json(cs, &unspentBoxesPtr) } try checkError(error) - return unspentInputBoxesPtr! + return unspentBoxesPtr! } deinit { - ergo_wallet_unspent_input_boxes_delete(self.pointer) + ergo_wallet_unspent_boxes_delete(self.pointer) } } @@ -137,7 +137,7 @@ class OutputBoxes { } deinit { - ergo_wallet_unspent_input_boxes_delete(self.pointer) + ergo_wallet_output_boxes_delete(self.pointer) } } @@ -165,7 +165,7 @@ class SecretKey { struct Wallet { static func new_signed_tx(ergoStateContext: ErgoStateContext, - unspentInputBoxes: UnspentInputBoxes, + unspentBoxes: UnspentBoxes, outputBoxes: OutputBoxes, sendChangeTo: Address, minChangeValue: UInt64, @@ -173,7 +173,7 @@ struct Wallet { secretKey: SecretKey) throws -> Transaction { var transactionPtr: TransactionPtr? let error = ergo_wallet_new_signed_tx(ergoStateContext.pointer, - unspentInputBoxes.pointer, + unspentBoxes.pointer, nil, // data input boxes outputBoxes.pointer, sendChangeTo.pointer, diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index 0dfd0af33..cd13d041f 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -88,17 +88,17 @@ impl SecretKey { /// Transaction inputs, array of ErgoBoxCandidate #[wasm_bindgen] -pub struct TxInputs(Vec); +pub struct UnspentBoxes(Vec); #[wasm_bindgen] -impl TxInputs { +impl UnspentBoxes { /// parse ErgoBoxCandidate array from json #[allow(clippy::boxed_local)] - pub fn from_boxes(_boxes: Box<[JsValue]>) -> TxInputs { + pub fn from_boxes(_boxes: Box<[JsValue]>) -> UnspentBoxes { // box in boxes.into_iter() { // let _box: chain::ErgoBoxCandidate = jbox.into_serde().unwrap(); // } - TxInputs(vec![]) + UnspentBoxes(vec![]) } } /// @@ -222,7 +222,8 @@ impl ErgoStateContext { } /// Create a signed transaction from: -/// `inputs` - boxes [`ErgoBoxCandidate`] that will be spent +/// `unspent_boxes` - unspent boxes [`ErgoBoxCandidate`] from which transaction +/// inputs (boxes to spend) will be selected /// `outputs` - boxes that will be created in this transaction /// `send_change_to` - address for the change (total value of input - total value of outputs) /// that will be put in a new box that will be added to `outputs` @@ -230,7 +231,7 @@ impl ErgoStateContext { #[wasm_bindgen] pub fn new_signed_transaction( _state_context: ErgoStateContext, - _inputs: TxInputs, + _unspent_boxes: UnspentBoxes, _data_inputs: TxDataInputs, _outputs: TxOutputs, _send_change_to: Address, From db779dbc57f78dc29e4824a8721a83878d1800eb Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 16 Jun 2020 17:58:29 +0300 Subject: [PATCH 18/20] sync WASM API with C API and fix WASM build; --- bindings/ergo-wallet-wasm/src/lib.rs | 2 ++ bindings/ergo-wallet-wasm/tests/test_transaction.js | 13 ++++++++++--- bindings/ergo-wallet-wasm/tests/transaction.rs | 4 +++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index cd13d041f..cd9099557 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -235,6 +235,8 @@ pub fn new_signed_transaction( _data_inputs: TxDataInputs, _outputs: TxOutputs, _send_change_to: Address, + _min_change_value: u32, + _tx_fee_amount: u32, _sk: SecretKey, ) -> Result { // not implemented, see https://github.com/ergoplatform/sigma-rust/issues/34 diff --git a/bindings/ergo-wallet-wasm/tests/test_transaction.js b/bindings/ergo-wallet-wasm/tests/test_transaction.js index 8a3012715..a78cd6853 100644 --- a/bindings/ergo-wallet-wasm/tests/test_transaction.js +++ b/bindings/ergo-wallet-wasm/tests/test_transaction.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import {TxInputs, TxDataInputs, SecretKey, ErgoBoxCandidate, Contract, TxOutputs, ErgoStateContext} from '../pkg/ergo_wallet_wasm'; +import {UnspentBoxes, TxDataInputs, SecretKey, ErgoBoxCandidate, Contract, TxOutputs, ErgoStateContext} from '../pkg/ergo_wallet_wasm'; const sigma_rust = import('../pkg/ergo_wallet_wasm'); @@ -11,7 +11,7 @@ it('new signed transaction', async () => { } = await sigma_rust; const recipient = Address.from_testnet_str('test'); - const tx_inputs = TxInputs.from_boxes([]); + const unspent_boxes = UnspentBoxes.from_boxes([]); const tx_data_inputs = TxDataInputs.from_boxes([]); const send_change_to = Address.from_testnet_str(''); const sk = SecretKey.parse(''); @@ -19,6 +19,13 @@ it('new signed transaction', async () => { let outbox = new ErgoBoxCandidate(1, 0, Contract.pay_to_address(recipient)); let tx_outputs = TxOutputs.from_boxes([outbox]); let dummy_ctx = ErgoStateContext.dummy(); - expect(() => new_signed_transaction(dummy_ctx, tx_inputs, tx_data_inputs, tx_outputs, send_change_to, sk)).to.throw("Not yet implemented"); + expect(() => new_signed_transaction(dummy_ctx, + unspent_boxes, + tx_data_inputs, + tx_outputs, + send_change_to, + 1, + 1, + sk)).to.throw("Not yet implemented"); }); diff --git a/bindings/ergo-wallet-wasm/tests/transaction.rs b/bindings/ergo-wallet-wasm/tests/transaction.rs index b1a3d726f..ca8dd9c3d 100644 --- a/bindings/ergo-wallet-wasm/tests/transaction.rs +++ b/bindings/ergo-wallet-wasm/tests/transaction.rs @@ -9,7 +9,7 @@ wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] fn test_signed_p2pk_transaction() { - let tx_inputs = TxInputs::from_boxes(Box::new([])); + let tx_inputs = UnspentBoxes::from_boxes(Box::new([])); let tx_data_inputs = TxDataInputs::from_boxes(Box::new([])); let send_change_to = Address::from_testnet_str("").expect("failed"); let sk = SecretKey::parse("").expect("failed"); @@ -25,6 +25,8 @@ fn test_signed_p2pk_transaction() { tx_data_inputs, tx_outputs, send_change_to, + 1, + 1, sk, ); assert!(res.is_err()); From d6214b3d3315cc1f8734265285eb05abcf62fa8c Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Wed, 17 Jun 2020 12:05:27 +0300 Subject: [PATCH 19/20] move new_signed_tx under new Wallet(loads from mnemonic); remove SecretKey in WASM and C APIs; --- bindings/ergo-wallet-c/h/ergo_wallet.h | 44 +++++++------ bindings/ergo-wallet-c/src/lib.rs | 43 ++++++------ .../Sources/ErgoWallet/ErgoWallet.swift | 57 +++++++++------- bindings/ergo-wallet-wasm/src/lib.rs | 65 +++++++++---------- .../tests/test_transaction.js | 18 ++--- .../ergo-wallet-wasm/tests/transaction.rs | 5 +- 6 files changed, 119 insertions(+), 113 deletions(-) diff --git a/bindings/ergo-wallet-c/h/ergo_wallet.h b/bindings/ergo-wallet-c/h/ergo_wallet.h index 3d4ebc8da..b33873eff 100644 --- a/bindings/ergo-wallet-c/h/ergo_wallet.h +++ b/bindings/ergo-wallet-c/h/ergo_wallet.h @@ -18,12 +18,12 @@ typedef struct Error Error; typedef struct OutputBoxes OutputBoxes; -typedef struct SecretKey SecretKey; - typedef struct Transaction Transaction; typedef struct UnspentBoxes UnspentBoxes; +typedef struct Wallet Wallet; + typedef Error *ErrorPtr; typedef Address *AddressPtr; @@ -34,13 +34,13 @@ typedef ErgoBoxCandidate *ErgoBoxCandidatePtr; typedef ErgoStateContext *ErgoStateContextPtr; -typedef UnspentBoxes *UnspentBoxesPtr; +typedef OutputBoxes *OutputBoxesPtr; -typedef DataInputBoxes *DataInputBoxesPtr; +typedef UnspentBoxes *UnspentBoxesPtr; -typedef OutputBoxes *OutputBoxesPtr; +typedef Wallet *WalletPtr; -typedef SecretKey *SecretKeyPtr; +typedef DataInputBoxes *DataInputBoxesPtr; ErrorPtr ergo_wallet_address_delete(AddressPtr _address); @@ -66,29 +66,31 @@ ErrorPtr ergo_wallet_ergo_state_context_from_json(const char *_json_str, char *ergo_wallet_error_to_string(ErrorPtr error); -ErrorPtr ergo_wallet_new_signed_tx(ErgoStateContextPtr _state_context, - UnspentBoxesPtr _unspent_boxes, - DataInputBoxesPtr _data_input_boxes, - OutputBoxesPtr _output_boxes, - AddressPtr _send_change_to, - uint64_t _min_change_value, - uint64_t _tx_fee_amount, - SecretKeyPtr _sk, - TransactionPtr *_transaction_out); - ErrorPtr ergo_wallet_output_boxes_delete(OutputBoxesPtr _output_boxes); ErrorPtr ergo_wallet_output_boxes_new(ErgoBoxCandidatePtr _ergo_box_candidate, OutputBoxesPtr *_output_boxes_out); -ErrorPtr ergo_wallet_secret_key_delete(SecretKeyPtr _secret_key); - -ErrorPtr ergo_wallet_secret_key_parse_str(const char *_secret_key_str, - SecretKeyPtr *_secret_key_out); - ErrorPtr ergo_wallet_signed_tx_to_json(TransactionPtr _transaction, const char **_json_str_out); ErrorPtr ergo_wallet_unspent_boxes_delete(UnspentBoxesPtr _unspent_boxes); ErrorPtr ergo_wallet_unspent_boxes_from_json(const char *_json_str, UnspentBoxesPtr *_unspent_boxes_out); + +ErrorPtr ergo_wallet_wallet_delete(WalletPtr _wallet); + +ErrorPtr ergo_wallet_wallet_from_mnemonic(const char *_mnemonic_phrase, + const uint8_t *_mnemonic_password, + uintptr_t _mnemonic_password_length, + WalletPtr *_wallet_out); + +ErrorPtr ergo_wallet_wallet_new_signed_tx(WalletPtr _wallet, + ErgoStateContextPtr _state_context, + UnspentBoxesPtr _unspent_boxes, + DataInputBoxesPtr _data_input_boxes, + OutputBoxesPtr _output_boxes, + AddressPtr _send_change_to, + uint64_t _min_change_value, + uint64_t _tx_fee_amount, + TransactionPtr *_transaction_out); diff --git a/bindings/ergo-wallet-c/src/lib.rs b/bindings/ergo-wallet-c/src/lib.rs index 08bb47229..2501da3c8 100644 --- a/bindings/ergo-wallet-c/src/lib.rs +++ b/bindings/ergo-wallet-c/src/lib.rs @@ -13,8 +13,7 @@ use sigma_tree::chain; use std::{ffi::CString, os::raw::c_char}; -// TODO: sync changes to WASM API -// TODO: share code with future JNI bindings +// TODO: share code with WASM(structs?) and future JNI bindings // TODO: add docs // TODO: extract into files/modules? @@ -39,22 +38,6 @@ pub unsafe extern "C" fn ergo_wallet_ergo_state_context_delete( todo!() } -pub struct SecretKey(ergo_wallet::SecretKey); -pub type SecretKeyPtr = *mut SecretKey; - -#[no_mangle] -pub extern "C" fn ergo_wallet_secret_key_parse_str( - _secret_key_str: *const c_char, - _secret_key_out: *mut SecretKeyPtr, -) -> ErrorPtr { - todo!() -} - -#[no_mangle] -pub extern "C" fn ergo_wallet_secret_key_delete(_secret_key: SecretKeyPtr) -> ErrorPtr { - todo!() -} - pub struct ErgoBoxCandidate(chain::ErgoBoxCandidate); pub type ErgoBoxCandidatePtr = *mut ErgoBoxCandidate; @@ -126,16 +109,34 @@ pub extern "C" fn ergo_wallet_output_boxes_delete(_output_boxes: OutputBoxesPtr) todo!() } +pub struct Wallet(); +pub type WalletPtr = *mut Wallet; + +#[no_mangle] +pub extern "C" fn ergo_wallet_wallet_from_mnemonic( + _mnemonic_phrase: *const c_char, + _mnemonic_password: *const u8, + _mnemonic_password_length: usize, + _wallet_out: *mut WalletPtr, +) -> ErrorPtr { + todo!() +} + +#[no_mangle] +pub extern "C" fn ergo_wallet_wallet_delete(_wallet: WalletPtr) -> ErrorPtr { + todo!() +} + #[no_mangle] -pub extern "C" fn ergo_wallet_new_signed_tx( - _state_context: ErgoStateContextPtr, // can be null or make "empty" func? +pub extern "C" fn ergo_wallet_wallet_new_signed_tx( + _wallet: WalletPtr, + _state_context: ErgoStateContextPtr, _unspent_boxes: UnspentBoxesPtr, _data_input_boxes: DataInputBoxesPtr, // can be null _output_boxes: OutputBoxesPtr, _send_change_to: AddressPtr, _min_change_value: u64, _tx_fee_amount: u64, - _sk: SecretKeyPtr, _transaction_out: *mut TransactionPtr, ) -> ErrorPtr { todo!() diff --git a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift index e633efecb..907d21ee3 100644 --- a/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift +++ b/bindings/ergo-wallet-ios/Sources/ErgoWallet/ErgoWallet.swift @@ -141,45 +141,54 @@ class OutputBoxes { } } -class SecretKey { - internal var pointer: SecretKeyPtr - - init(withString secretKeyStr: String) throws { - self.pointer = try SecretKey.fromString(secretKeyStr: secretKeyStr) - } - - private static func fromString(secretKeyStr: String) throws -> SecretKeyPtr { - var ptr: SecretKeyPtr? - let error = secretKeyStr.withCString { cs in - ergo_wallet_secret_key_parse_str(cs, &ptr) +// class SecretKey { +// internal var pointer: SecretKeyPtr + +// init(withString secretKeyStr: String) throws { +// self.pointer = try SecretKey.fromString(secretKeyStr: secretKeyStr) +// } + +// private static func fromString(secretKeyStr: String) throws -> SecretKeyPtr { +// var ptr: SecretKeyPtr? +// let error = secretKeyStr.withCString { cs in +// ergo_wallet_secret_key_parse_str(cs, &ptr) +// } +// try checkError(error) +// return ptr! +// } + +// deinit { +// ergo_wallet_secret_key_delete(self.pointer) +// } +// } + +class Wallet { + internal var pointer: WalletPtr + + init(withMnemonic mnemonicPhrase: String) throws { + var ptr: WalletPtr? + let error = mnemonicPhrase.withCString { mnemonicPhraseC in + ergo_wallet_wallet_from_mnemonic(mnemonicPhraseC, nil, 0, &ptr) } try checkError(error) - return ptr! - } - - deinit { - ergo_wallet_secret_key_delete(self.pointer) + self.pointer = ptr! } -} - -struct Wallet { - static func new_signed_tx(ergoStateContext: ErgoStateContext, + func new_signed_tx(ergoStateContext: ErgoStateContext, unspentBoxes: UnspentBoxes, outputBoxes: OutputBoxes, sendChangeTo: Address, minChangeValue: UInt64, - txFeeAmount: UInt64, - secretKey: SecretKey) throws -> Transaction { + txFeeAmount: UInt64) throws -> Transaction { var transactionPtr: TransactionPtr? - let error = ergo_wallet_new_signed_tx(ergoStateContext.pointer, + let error = ergo_wallet_wallet_new_signed_tx(self.pointer, + ergoStateContext.pointer, unspentBoxes.pointer, nil, // data input boxes outputBoxes.pointer, sendChangeTo.pointer, minChangeValue, txFeeAmount, - secretKey.pointer, &transactionPtr) try checkError(error) return Transaction(withRawPointer: transactionPtr!) diff --git a/bindings/ergo-wallet-wasm/src/lib.rs b/bindings/ergo-wallet-wasm/src/lib.rs index cd9099557..db816861b 100644 --- a/bindings/ergo-wallet-wasm/src/lib.rs +++ b/bindings/ergo-wallet-wasm/src/lib.rs @@ -73,19 +73,6 @@ impl Address { } } -/// Secret key for prover -#[wasm_bindgen] -pub struct SecretKey(ergo_wallet::SecretKey); - -#[wasm_bindgen] -impl SecretKey { - /// Decode from string - pub fn parse(_: &str) -> Result { - // not implemented, see https://github.com/ergoplatform/sigma-rust/issues/33 - Ok(SecretKey(ergo_wallet::SecretKey::random_dlog())) - } -} - /// Transaction inputs, array of ErgoBoxCandidate #[wasm_bindgen] pub struct UnspentBoxes(Vec); @@ -221,24 +208,36 @@ impl ErgoStateContext { } } -/// Create a signed transaction from: -/// `unspent_boxes` - unspent boxes [`ErgoBoxCandidate`] from which transaction -/// inputs (boxes to spend) will be selected -/// `outputs` - boxes that will be created in this transaction -/// `send_change_to` - address for the change (total value of input - total value of outputs) -/// that will be put in a new box that will be added to `outputs` -/// `sk` - secret key to sign the transaction (make proofs for inputs) -#[wasm_bindgen] -pub fn new_signed_transaction( - _state_context: ErgoStateContext, - _unspent_boxes: UnspentBoxes, - _data_inputs: TxDataInputs, - _outputs: TxOutputs, - _send_change_to: Address, - _min_change_value: u32, - _tx_fee_amount: u32, - _sk: SecretKey, -) -> Result { - // not implemented, see https://github.com/ergoplatform/sigma-rust/issues/34 - Err(JsValue::from_str("Not yet implemented")) +/// TBD +#[wasm_bindgen] +pub struct Wallet(); + +#[wasm_bindgen] +impl Wallet { + /// Create wallet instance loading secret key from mnemonic + pub fn from_mnemonic(_mnemonic_phrase: &str, _mnemonic_pass: &str) -> Wallet { + Wallet() + } + + /// Create a signed transaction from: + /// `unspent_boxes` - unspent boxes [`ErgoBoxCandidate`] from which transaction + /// inputs (boxes to spend) will be selected + /// `outputs` - boxes that will be created in this transaction + /// `send_change_to` - address for the change (total value of input - total value of outputs) + /// that will be put in a new box that will be added to `outputs` + /// `sk` - secret key to sign the transaction (make proofs for inputs) + #[wasm_bindgen] + pub fn new_signed_transaction( + &self, + _state_context: ErgoStateContext, + _unspent_boxes: UnspentBoxes, + _data_inputs: TxDataInputs, + _outputs: TxOutputs, + _send_change_to: Address, + _min_change_value: u32, + _tx_fee_amount: u32, + ) -> Result { + // not implemented, see https://github.com/ergoplatform/sigma-rust/issues/34 + Err(JsValue::from_str("Not yet implemented")) + } } diff --git a/bindings/ergo-wallet-wasm/tests/test_transaction.js b/bindings/ergo-wallet-wasm/tests/test_transaction.js index a78cd6853..075882d9b 100644 --- a/bindings/ergo-wallet-wasm/tests/test_transaction.js +++ b/bindings/ergo-wallet-wasm/tests/test_transaction.js @@ -1,31 +1,27 @@ import { expect } from 'chai'; -import {UnspentBoxes, TxDataInputs, SecretKey, ErgoBoxCandidate, Contract, TxOutputs, ErgoStateContext} from '../pkg/ergo_wallet_wasm'; - -const sigma_rust = import('../pkg/ergo_wallet_wasm'); +import { + Address, Wallet, UnspentBoxes, TxDataInputs, ErgoBoxCandidate, Contract, + TxOutputs, ErgoStateContext +} from '../pkg/ergo_wallet_wasm'; it('new signed transaction', async () => { - const { - Address, - new_signed_transaction, - } = await sigma_rust; const recipient = Address.from_testnet_str('test'); const unspent_boxes = UnspentBoxes.from_boxes([]); const tx_data_inputs = TxDataInputs.from_boxes([]); const send_change_to = Address.from_testnet_str(''); - const sk = SecretKey.parse(''); let outbox = new ErgoBoxCandidate(1, 0, Contract.pay_to_address(recipient)); let tx_outputs = TxOutputs.from_boxes([outbox]); let dummy_ctx = ErgoStateContext.dummy(); - expect(() => new_signed_transaction(dummy_ctx, + let wallet = Wallet.from_mnemonic("", ""); + expect(() => wallet.new_signed_transaction(dummy_ctx, unspent_boxes, tx_data_inputs, tx_outputs, send_change_to, 1, - 1, - sk)).to.throw("Not yet implemented"); + 1)).to.throw("Not yet implemented"); }); diff --git a/bindings/ergo-wallet-wasm/tests/transaction.rs b/bindings/ergo-wallet-wasm/tests/transaction.rs index ca8dd9c3d..4c61d1104 100644 --- a/bindings/ergo-wallet-wasm/tests/transaction.rs +++ b/bindings/ergo-wallet-wasm/tests/transaction.rs @@ -12,14 +12,14 @@ fn test_signed_p2pk_transaction() { let tx_inputs = UnspentBoxes::from_boxes(Box::new([])); let tx_data_inputs = TxDataInputs::from_boxes(Box::new([])); let send_change_to = Address::from_testnet_str("").expect("failed"); - let sk = SecretKey::parse("").expect("failed"); let recipient = Address::from_testnet_str("").expect("failed"); let outbox = ErgoBoxCandidate::new(1, 0, Contract::pay_to_address(recipient)); let out_boxes = [outbox.to_json().expect("failed")]; let tx_outputs = TxOutputs::from_boxes(Box::new(out_boxes)); let dummy_ctx = ErgoStateContext::dummy(); - let res = new_signed_transaction( + let wallet = Wallet::from_mnemonic("", ""); + let res = wallet.new_signed_transaction( dummy_ctx, tx_inputs, tx_data_inputs, @@ -27,7 +27,6 @@ fn test_signed_p2pk_transaction() { send_change_to, 1, 1, - sk, ); assert!(res.is_err()); } From fba0613ffe2e5aafe2500c7b8ad204a4c4f37e56 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Wed, 17 Jun 2020 12:10:29 +0300 Subject: [PATCH 20/20] update Xcode on CI; --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c767768cd..92edc71b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,7 +88,7 @@ matrix: - name: build for iOS os: osx - osx_image: xcode11.3 + osx_image: xcode11.5 rust: stable before_install: - rustup target add aarch64-apple-ios x86_64-apple-ios