From 94960b3edd255a04c6c50316e2f31b545596d258 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Fri, 22 Mar 2019 12:03:25 +0000 Subject: [PATCH] [WIP] V2 API Doctest generation (#24) V2 API Doctest generation --- Cargo.lock | 108 +-- api/Cargo.toml | 6 +- api/src/foreign.rs | 2 +- api/src/lib.rs | 3 + api/src/owner.rs | 683 +++++++++----- api/src/owner_rpc.rs | 1124 ++++++++++++++++++------ controller/Cargo.toml | 2 +- controller/src/command.rs | 8 +- controller/src/controller.rs | 11 +- controller/src/display.rs | 31 +- controller/tests/accounts.rs | 6 +- controller/tests/check.rs | 18 +- controller/tests/file.rs | 6 +- controller/tests/repost.rs | 14 +- controller/tests/restore.rs | 18 +- controller/tests/self_send.rs | 6 +- controller/tests/transaction.rs | 42 +- impls/Cargo.toml | 2 +- impls/src/adapters/keybase.rs | 2 +- impls/src/test_framework/mod.rs | 12 +- impls/src/test_framework/testclient.rs | 2 +- integration/tests/framework.rs | 15 +- integration/tests/simulnet.rs | 7 +- libwallet/Cargo.toml | 3 +- libwallet/src/api_impl/foreign.rs | 3 +- libwallet/src/api_impl/owner.rs | 40 +- libwallet/src/internal/restore.rs | 18 +- libwallet/src/internal/selection.rs | 4 + libwallet/src/internal/tx.rs | 25 +- libwallet/src/internal/updater.rs | 14 +- libwallet/src/lib.rs | 2 + libwallet/src/slate.rs | 47 +- libwallet/src/slate_versions/v2.rs | 7 + libwallet/src/types.rs | 53 +- libwallet/tests/libwallet.rs | 8 +- libwallet/tests/slates/v2.slate | 14 +- src/bin/cmd/wallet_tests.rs | 4 +- 37 files changed, 1645 insertions(+), 725 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e299310..c41dbb74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "adler32" version = "1.0.3" @@ -88,7 +90,7 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -190,7 +192,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -286,7 +288,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -473,7 +475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "flate2" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -553,7 +555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "grin_api" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -585,7 +587,7 @@ dependencies = [ [[package]] name = "grin_chain" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -599,7 +601,7 @@ dependencies = [ "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -608,7 +610,7 @@ dependencies = [ [[package]] name = "grin_core" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -621,7 +623,7 @@ dependencies = [ "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -634,7 +636,7 @@ dependencies = [ [[package]] name = "grin_keychain" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -656,7 +658,7 @@ dependencies = [ [[package]] name = "grin_p2p" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -676,7 +678,7 @@ dependencies = [ [[package]] name = "grin_pool" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -709,7 +711,7 @@ dependencies = [ [[package]] name = "grin_store" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -729,7 +731,7 @@ dependencies = [ [[package]] name = "grin_util" version = "1.1.0" -source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#c3496b45dd2704b6d542dad3447e8649d25399e4" +source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#2e72ed91f3d1616d9c553e97d489bc2e6b4032b1" dependencies = [ "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -777,6 +779,7 @@ dependencies = [ name = "grin_wallet_api" version = "1.1.0" dependencies = [ + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "easy-jsonrpc 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -792,7 +795,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -839,7 +842,7 @@ dependencies = [ "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -868,7 +871,7 @@ dependencies = [ "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -884,17 +887,18 @@ dependencies = [ "grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)", "grin_wallet_config 1.1.0", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "h2" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -957,7 +961,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1063,7 +1067,7 @@ name = "libgit2-sys" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1083,7 +1087,7 @@ name = "libloading" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1092,7 +1096,7 @@ name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1110,12 +1114,7 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "linked-hash-map" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1160,7 +1159,7 @@ dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1178,10 +1177,10 @@ dependencies = [ [[package]] name = "lru-cache" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1221,7 +1220,7 @@ name = "miniz-sys" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1238,7 +1237,7 @@ name = "miniz_oxide_c_api" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1336,7 +1335,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1493,7 +1492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ordered-float" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1871,7 +1870,7 @@ name = "ring" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2009,7 +2008,7 @@ name = "serde-value" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2039,7 +2038,7 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2308,7 +2307,7 @@ dependencies = [ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2342,7 +2341,7 @@ dependencies = [ [[package]] name = "tokio-sync" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2525,6 +2524,15 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "uuid" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vcpkg" version = "0.2.6" @@ -2656,7 +2664,7 @@ name = "yaml-rust" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2699,7 +2707,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" "checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" @@ -2732,7 +2740,7 @@ dependencies = [ "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" +"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" @@ -2752,7 +2760,7 @@ dependencies = [ "checksum grin_secp256k1zkp 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "75e9a265f3eeea4c204470f7262e2c6fe18f3d8ddf5fb24340cb550ac4f909c5" "checksum grin_store 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" "checksum grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "" -"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" @@ -2774,14 +2782,13 @@ dependencies = [ "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum linefeed 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2abb5810ef55bb5f5f33b010cc280b3ab877764c902681efc7c8c95628004c" -"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" -"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "13416eee745b087c22934f35f1f24da22da41ba2a5ce197143d168ce055cc58d" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum log-mdc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" "checksum log4rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25e0fc8737a634116a2deb38d821e4400ed16ce9dcb0d628a978d399260f5902" -"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" @@ -2815,7 +2822,7 @@ dependencies = [ "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" -"checksum ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0015e9e8e28ee20c581cfbfe47c650cedeb9ed0721090e0b7ebb10b9cdbcc2" +"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -2911,7 +2918,7 @@ dependencies = [ "checksum tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05746ae87dca83a2016b4f5dba5b237b897dd12fd324f60afe282112f16969a" "checksum tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "208d62fa3e015426e3c64039d9d20adf054a3c9b4d9445560f1c41c75bef3eab" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fda385df506bf7546e70872767f71e81640f1f251bdf2fd8eb81a0eaec5fe022" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" @@ -2933,6 +2940,7 @@ dependencies = [ "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" +"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" diff --git a/api/Cargo.toml b/api/Cargo.toml index 59addac8..1a5bb0f4 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -14,11 +14,14 @@ edition = "2018" failure = "0.1" failure_derive = "0.1" log = "0.4" -uuid = { version = "0.6", features = ["serde", "v4"] } +uuid = { version = "0.7", features = ["serde", "v4"] } +serde_json = "1" easy-jsonrpc = "0.4.1" +chrono = { version = "0.4.4", features = ["serde"] } grin_wallet_libwallet = { path = "../libwallet", version = "1.1.0" } grin_wallet_config = { path = "../config", version = "1.1.0" } +grin_wallet_impls = { path = "../impls", version = "1.1.0" } grin_core = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" } grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" } @@ -28,6 +31,5 @@ grin_api = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1 grin_store = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" } [dev-dependencies] -grin_wallet_impls = { path = "../impls", version = "1.1.0" } serde_json = "1" tempfile = "3.0.7" diff --git a/api/src/foreign.rs b/api/src/foreign.rs index d2aefc6c..6da5412a 100644 --- a/api/src/foreign.rs +++ b/api/src/foreign.rs @@ -88,7 +88,7 @@ where ) -> Result<(), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; - let res = foreign::receive_tx(&mut *w, slate, dest_acct_name, message); + let res = foreign::receive_tx(&mut *w, slate, dest_acct_name, message, false); w.close()?; res } diff --git a/api/src/lib.rs b/api/src/lib.rs index efb06fe6..d1b97346 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -29,6 +29,7 @@ extern crate grin_util as util; extern crate grin_wallet_libwallet as libwallet; extern crate failure_derive; +extern crate serde_json; #[macro_use] extern crate log; @@ -41,3 +42,5 @@ pub use crate::foreign::Foreign; pub use crate::foreign_rpc::ForeignRpc; pub use crate::owner::Owner; pub use crate::owner_rpc::OwnerRpc; + +pub use crate::owner_rpc::run_doctest; diff --git a/api/src/owner.rs b/api/src/owner.rs index a96f8d1f..548b3e67 100644 --- a/api/src/owner.rs +++ b/api/src/owner.rs @@ -27,6 +27,7 @@ //! seed). use crate::util::Mutex; +use chrono::prelude::*; use std::marker::PhantomData; use std::sync::Arc; use uuid::Uuid; @@ -36,10 +37,10 @@ use crate::keychain::{Identifier, Keychain}; use crate::libwallet::api_impl::owner; use crate::libwallet::slate::Slate; use crate::libwallet::types::{ - AcctPathMapping, NodeClient, OutputData, TxLogEntry, WalletBackend, WalletInfo, + AcctPathMapping, NodeClient, OutputCommitMapping, TxEstimation, TxLogEntry, WalletBackend, + WalletInfo, }; use crate::libwallet::Error; -use crate::util::secp::pedersen; /// Functions intended for use by the owner (e.g. master seed holder) of the wallet. pub struct Owner @@ -49,8 +50,10 @@ where K: Keychain, { /// A reference-counted mutex to an implementation of the - /// [`WalletBackend`](../types/trait.WalletBackend.html) trait. + /// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait. pub wallet: Arc>, + /// Flag to normalize some output during testing. Can mostly be ignored. + pub doctest_mode: bool, phantom: PhantomData, phantom_c: PhantomData, } @@ -64,37 +67,46 @@ where /// Create a new API instance with the given wallet instance. All subsequent /// API calls will operate on this instance of the wallet. /// - /// Each method will call the [`WalletBackend`](../types/trait.WalletBackend.html)'s - /// [`open_with_credentials`](../types/trait.WalletBackend.html#tymethod.open_with_credentials) + /// Each method will call the [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html)'s + /// [`open_with_credentials`](../grin_wallet_libwallet/types/trait.WalletBackend.html#tymethod.open_with_credentials) /// (initialising a keychain with the master seed,) perform its operation, then close the keychain - /// with a call to [`close`](../types/trait.WalletBackend.html#tymethod.close) + /// with a call to [`close`](../grin_wallet_libwallet/types/trait.WalletBackend.html#tymethod.close) /// /// # Arguments /// * `wallet_in` - A reference-counted mutex containing an implementation of the - /// [`WalletBackend`](../types/trait.WalletBackend.html) trait. + /// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait. /// /// # Returns /// * An instance of the OwnerApi holding a reference to the provided wallet /// /// # Example - /// ``` ignore - /// # extern crate grin_wallet_config as config; - /// # extern crate grin_refwallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; + /// ``` + /// use grin_keychain as keychain; + /// use grin_util as util; + /// use grin_wallet_api as api; + /// use grin_wallet_config as config; + /// use grin_wallet_impls as impls; + /// use grin_wallet_libwallet as libwallet; + /// + /// use keychain::ExtKeychain; + /// use tempfile::tempdir; /// /// use std::sync::Arc; /// use util::Mutex; /// - /// use keychain::ExtKeychain; - /// use wallet::libwallet::api::Owner; - /// - /// // These contain sample implementations of each part needed for a wallet - /// use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend}; + /// use api::Owner; /// use config::WalletConfig; + /// use impls::{HTTPNodeClient, LMDBBackend}; + /// use libwallet::types::WalletBackend; /// /// let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); + /// # let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap(); + /// # let dir = dir + /// # .path() + /// # .to_str() + /// # .ok_or("Failed to convert tmpdir path to string.".to_owned()) + /// # .unwrap(); + /// # wallet_config.data_file_dir = dir.to_owned(); /// /// // A NodeClient must first be created to handle communication between /// // the wallet and the node. @@ -113,6 +125,7 @@ where pub fn new(wallet_in: Arc>) -> Self { Owner { wallet: wallet_in, + doctest_mode: false, phantom: PhantomData, phantom_c: PhantomData, } @@ -123,8 +136,8 @@ where /// /// # Returns /// * Result Containing: - /// * A Vector of [`AcctPathMapping`](../types/struct.AcctPathMapping.html) data - /// * or [`libwallet::Error`](../struct.Error.html) if an error is encountered. + /// * A Vector of [`AcctPathMapping`](../grin_wallet_libwallet/types/struct.AcctPathMapping.html) data + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. /// /// # Remarks /// @@ -134,24 +147,8 @@ where /// /// # Example /// Set up as in [`new`](struct.Owner.html#method.new) method above. - /// ``` ignore - /// # extern crate grin_wallet_config as config; - /// # extern crate grin_refwallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; - /// # use std::sync::Arc; - /// # use util::Mutex; - /// # use keychain::ExtKeychain; - /// # use wallet::libwallet::api::Owner; - /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend}; - /// # use config::WalletConfig; - /// # let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); - /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - /// # let mut wallet:Arc>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let api_owner = Owner::new(wallet.clone()); /// @@ -175,8 +172,8 @@ where /// /// # Returns /// * Result Containing: - /// * A [Keychain Identifier](#) for the new path - /// * or [`libwallet::Error`](../struct.Error.html) if an error is encountered. + /// * A [Keychain Identifier](../grin_keychain/struct.Identifier.html) for the new path + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. /// /// # Remarks /// @@ -192,22 +189,8 @@ where /// /// # Example /// Set up as in [`new`](struct.Owner.html#method.new) method above. - /// ``` ignore - /// # extern crate grin_wallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; - /// # use std::sync::Arc; - /// # use util::Mutex; - /// # use keychain::ExtKeychain; - /// # use wallet::libwallet::api::Owner; - /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; - /// # let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); - /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - /// # let mut wallet:Arc>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let api_owner = Owner::new(wallet.clone()); /// @@ -233,7 +216,7 @@ where /// # Returns /// * Result Containing: /// * `Ok(())` if the path was correctly set - /// * or [`libwallet::Error`](../struct.Error.html) if an error is encountered. + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. /// /// # Remarks /// @@ -246,22 +229,8 @@ where /// /// # Example /// Set up as in [`new`](struct.Owner.html#method.new) method above. - /// ``` ignore - /// # extern crate grin_wallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; - /// # use std::sync::Arc; - /// # use util::Mutex; - /// # use keychain::ExtKeychain; - /// # use wallet::libwallet::api::Owner; - /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; - /// # let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); - /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - /// # let mut wallet:Arc>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let api_owner = Owner::new(wallet.clone()); /// @@ -285,7 +254,7 @@ where /// in the wallet will be returned. If `false`, spent outputs will omitted /// from the results. /// * `refresh_from_node` - If true, the wallet will attempt to contact - /// a node (via the [`NodeClient`](../types/trait.NodeClient.html) + /// a node (via the [`NodeClient`](../grin_wallet_libwallet/types/trait.NodeClient.html) /// provided during wallet instantiation). If `false`, the results will /// contain output information that may be out-of-date (from the last time /// the wallet's output set was refreshed against the node). @@ -293,32 +262,20 @@ where /// the transaction log entry of id `i`. /// /// # Returns - /// * (`bool`, `Vec`) - A tuple: + /// * `(bool, Vec)` - A tuple: /// * The first `bool` element indicates whether the data was successfully /// refreshed from the node (note this may be false even if the `refresh_from_node` /// argument was set to `true`. - /// * The second element contains the result set, of which each element is - /// a mapping between the wallet's internal [OutputData](../types/struct.OutputData.html) + /// * The second element contains a vector of + /// [OutputCommitMapping](../grin_wallet_libwallet/types/struct.OutputCommitMapping.html) + /// of which each element is a mapping between the wallet's internal + /// [OutputData](../grin_wallet_libwallet/types/struct.Output.html) /// and the Output commitment as identified in the chain's UTXO set /// /// # Example /// Set up as in [`new`](struct.Owner.html#method.new) method above. - /// ``` ignore - /// # extern crate grin_wallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; - /// # use std::sync::Arc; - /// # use util::Mutex; - /// # use keychain::ExtKeychain; - /// # use wallet::libwallet::api::Owner; - /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; - /// # let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); - /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - /// # let mut wallet:Arc>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let api_owner = Owner::new(wallet.clone()); /// let show_spent = false; @@ -327,7 +284,7 @@ where /// /// let result = api_owner.retrieve_outputs(show_spent, update_from_node, tx_id); /// - /// if let Ok((was_updated, output_mapping)) = result { + /// if let Ok((was_updated, output_mappings)) = result { /// //... /// } /// ``` @@ -337,7 +294,7 @@ where include_spent: bool, refresh_from_node: bool, tx_id: Option, - ) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error> { + ) -> Result<(bool, Vec), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; let res = owner::retrieve_outputs(&mut *w, include_spent, refresh_from_node, tx_id); @@ -345,46 +302,32 @@ where res } - /// Returns a list of [Transaction Log Entries](../types/struct.TxLogEntry.html) + /// Returns a list of [Transaction Log Entries](../grin_wallet_libwallet/types/struct.TxLogEntry.html) /// from the active account in the wallet. /// /// # Arguments /// * `refresh_from_node` - If true, the wallet will attempt to contact - /// a node (via the [`NodeClient`](../types/trait.NodeClient.html) + /// a node (via the [`NodeClient`](../grin_wallet_libwallet/types/trait.NodeClient.html) /// provided during wallet instantiation). If `false`, the results will /// contain transaction information that may be out-of-date (from the last time /// the wallet's output set was refreshed against the node). /// * `tx_id` - If `Some(i)`, only return the transactions associated with /// the transaction log entry of id `i`. /// * `tx_slate_id` - If `Some(uuid)`, only return transactions associated with - /// the given [`Slate`](../../libtx/slate/struct.Slate.html) uuid. + /// the given [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html) uuid. /// /// # Returns - /// * (`bool`, `Vec<[TxLogEntry](../types/struct.TxLogEntry.html)>`) - A tuple: + /// * `(bool, Vec>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let api_owner = Owner::new(wallet.clone()); /// let update_from_node = true; @@ -407,16 +350,27 @@ where ) -> Result<(bool, Vec), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; - let res = owner::retrieve_txs(&mut *w, refresh_from_node, tx_id, tx_slate_id); + let mut res = owner::retrieve_txs(&mut *w, refresh_from_node, tx_id, tx_slate_id)?; + if self.doctest_mode { + res.1 = res + .1 + .into_iter() + .map(|mut t| { + t.confirmation_ts = Some(Utc.ymd(2019, 1, 15).and_hms(16, 1, 26)); + t.creation_ts = Utc.ymd(2019, 1, 15).and_hms(16, 1, 26); + t + }) + .collect(); + } w.close()?; - res + Ok(res) } /// Returns summary information from the active account in the wallet. /// /// # Arguments /// * `refresh_from_node` - If true, the wallet will attempt to contact - /// a node (via the [`NodeClient`](../types/trait.NodeClient.html) + /// a node (via the [`NodeClient`](../grin_wallet_libwallet/types/trait.NodeClient.html) /// provided during wallet instantiation). If `false`, the results will /// contain transaction information that may be out-of-date (from the last time /// the wallet's output set was refreshed against the node). @@ -424,30 +378,16 @@ where /// should have before it's included in the 'amount_currently_spendable' total /// /// # Returns - /// * (`bool`, [`WalletInfo`](../types/struct.WalletInfo.html)) - A tuple: + /// * (`bool`, [`WalletInfo`](../grin_wallet_libwallet/types/struct.WalletInfo.html)) - A tuple: /// * The first `bool` element indicates whether the data was successfully /// refreshed from the node (note this may be false even if the `refresh_from_node` /// argument was set to `true`. - /// * The second element contains the Summary [`WalletInfo`](../types/struct.WalletInfo.html) + /// * The second element contains the Summary [`WalletInfo`](../grin_wallet_libwallet/types/struct.WalletInfo.html) /// /// # Example /// Set up as in [`new`](struct.Owner.html#method.new) method above. - /// ``` ignore - /// # extern crate grin_wallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; - /// # use std::sync::Arc; - /// # use util::Mutex; - /// # use keychain::ExtKeychain; - /// # use wallet::libwallet::api::Owner; - /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; - /// # let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); - /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - /// # let mut wallet:Arc>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let mut api_owner = Owner::new(wallet.clone()); /// let update_from_node = true; @@ -474,10 +414,10 @@ where } /// Initiates a new transaction as the sender, creating a new - /// [`Slate`](../../libtx/slate/struct.Slate.html) object containing + /// [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html) object containing /// the sender's inputs, change outputs, and public signature data. This slate can /// then be sent to the recipient to continue the transaction via the - /// [Foreign API's `receive_tx`](struct.APIForeign.html#method.receive_tx) method. + /// [Foreign API's `receive_tx`](struct.Foreign.html#method.receive_tx) method. /// /// When a transaction is created, the wallet must also lock inputs (and create unconfirmed /// outputs) corresponding to the transaction created in the slate, so that the wallet doesn't @@ -518,16 +458,19 @@ where /// the convenience of the participants during the exchange; it is not included in the final /// transaction sent to the chain. The message will be truncated to 256 characters. /// Validation of this message is optional. + /// * `target_slate_version` Optionally set the output target slate version (acceptable + /// down to the minimum slate version compatible with the current. If `None` the slate + /// is generated with the latest version. /// /// # Returns /// * a result containing: - /// * ([`Slate`](../../libtx/slate/struct.Slate.html), lock_function) - A tuple: - /// * The transaction Slate, which can be forwarded to the recieving party by any means. - /// * A lock function, which should be called when the caller deems it appropriate to lock - /// the transaction outputs (i.e. there is relative certaintly that the slate will be - /// transmitted to the receiving party). Must be called before calling + /// * The transaction [Slate](../grin_wallet_libwallet/slate/struct.Slate.html), + /// which can be forwarded to the recieving party by any means. Once the caller is relatively + /// certain that the transaction has been sent to the recipient, the associated wallet + /// transaction outputs should be locked via a call to + /// [`tx_lock_outputs`](struct.Owner.html#method.tx_lock_outputs). This must be called before calling /// [`finalize_tx`](struct.Owner.html#method.finalize_tx). - /// * or [`libwallet::Error`](../struct.Error.html) if an error is encountered. + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. /// /// # Remarks /// @@ -538,22 +481,8 @@ where /// /// # Example /// Set up as in [new](struct.Owner.html#method.new) method above. - /// ``` ignore - /// # extern crate grin_wallet as wallet; - /// # extern crate grin_keychain as keychain; - /// # extern crate grin_util as util; - /// # use std::sync::Arc; - /// # use util::Mutex; - /// # use keychain::ExtKeychain; - /// # use wallet::libwallet::api::Owner; - /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; - /// # let mut wallet_config = WalletConfig::default(); - /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); - /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - /// # let mut wallet:Arc>> = - /// # Arc::new(Mutex::new( - /// # LMDBBackend::new(wallet_config.clone(), "", node_client).unwrap() - /// # )); + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); /// /// let mut api_owner = Owner::new(wallet.clone()); /// let amount = 2_000_000_000; @@ -567,13 +496,14 @@ where /// 1, // num change outputs /// true, // select all outputs /// Some("Have some Grins. Love, Yeastplume".to_owned()), + /// None, // Use the default slate version /// ); /// - /// if let Ok((slate, lock_fn)) = result { + /// if let Ok(slate) = result { /// // Send slate somehow /// // ... /// // Lock our outputs if we're happy the slate was (or is being) sent - /// api_owner.tx_lock_outputs(&slate, lock_fn); + /// api_owner.tx_lock_outputs(&slate); /// } /// ``` @@ -600,41 +530,44 @@ where selection_strategy_is_use_all, message, target_slate_version, + self.doctest_mode, ); w.close()?; res } - /// Estimates the amount to be locked and fee for the transaction without creating one + /// Estimates the amount to be locked and fee for the transaction without creating one. /// /// # Arguments - /// * `src_acct_name` - The human readable account name from which to draw outputs - /// for the transaction, overriding whatever the active account is as set via the - /// [`set_active_account`](struct.Owner.html#method.set_active_account) method. - /// If None, the transaction will use the active account. - /// * `amount` - The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`) - /// * `minimum_confirmations` - The minimum number of confirmations an output - /// should have in order to be included in the transaction. - /// * `max_outputs` - By default, the wallet selects as many inputs as possible in a - /// transaction, to reduce the Output set and the fees. The wallet will attempt to spend - /// include up to `max_outputs` in a transaction, however if this is not enough to cover - /// the whole amount, the wallet will include more outputs. This parameter should be considered - /// a soft limit. - /// * `num_change_outputs` - The target number of change outputs to create in the transaction. - /// The actual number created will be `num_change_outputs` + whatever remainder is needed. - /// * `selection_strategy_is_use_all` - If `true`, attempt to use up as many outputs as - /// possible to create the transaction, up the 'soft limit' of `max_outputs`. This helps - /// to reduce the size of the UTXO set and the amount of data stored in the wallet, and - /// minimizes fees. This will generally result in many inputs and a large change output(s), - /// usually much larger than the amount being sent. If `false`, the transaction will include - /// as many outputs as are needed to meet the amount, (and no more) starting with the smallest - /// value outputs. + /// * As found in [`initiate_tx`](struct.Owner.html#method.initiate_tx) above. /// /// # Returns - /// * a result containing: - /// * (total, fee) - A tuple: - /// * Total amount to be locked. - /// * Transaction fee + /// * a result containing a + /// [`TxEstimation`](../grin_wallet_libwallet/types/struct.TxEstimation.html) + /// + /// # Example + /// Set up as in [new](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let mut api_owner = Owner::new(wallet.clone()); + /// let amount = 2_000_000_000; + /// + /// // Estimate transaction using default account + /// let result = api_owner.estimate_initiate_tx( + /// None, + /// amount, // amount + /// 10, // minimum confirmations + /// 500, // max outputs + /// 1, // num change outputs + /// true, // select all outputs + /// ); + /// + /// if let Ok(est) = result { + /// // ... + /// } + /// ``` + pub fn estimate_initiate_tx( &self, src_acct_name: Option<&str>, @@ -643,13 +576,7 @@ where max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, - ) -> Result< - ( - u64, // total - u64, // fee - ), - Error, - > { + ) -> Result { let mut w = self.wallet.lock(); w.open_with_credentials()?; let res = owner::estimate_initiate_tx( @@ -665,8 +592,56 @@ where res } - /// Lock outputs associated with a given slate/transaction - /// and create any outputs needed + /// Locks the outputs associated with the inputs to the transaction in the given + /// [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html), + /// making them unavailable for use in further transactions. This function is called + /// by the sender, (or more generally, all parties who have put inputs into the transaction,) + /// and must be called before the corresponding call to [`finalize_tx`](struct.Owner.html#method.finalize_tx) + /// that completes the transaction. + /// + /// Outputs will generally remain locked until they are removed from the chain, + /// at which point they will become `Spent`. It is commonplace for transactions not to complete + /// for various reasons over which a particular wallet has no control. For this reason, + /// [`cancel_tx`](struct.Owner.html#method.cancel_tx) can be used to manually unlock outputs + /// and return them to the `Unspent` state. + /// + /// # Arguments + /// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). All + /// elements in the `input` vector of the `tx` field that are found in the wallet's currently + /// active account will be set to status `Locked` + /// + /// # Returns + /// * Ok(()) if successful + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let mut api_owner = Owner::new(wallet.clone()); + /// let amount = 2_000_000_000; + /// + /// // Attempt to create a transaction using the 'default' account + /// let result = api_owner.initiate_tx( + /// None, + /// amount, // amount + /// 10, // minimum confirmations + /// 500, // max outputs + /// 1, // num change outputs + /// true, // select all outputs + /// Some("Remember to lock when we're happy this is sent".to_owned()), + /// None, // Use the default slate version + /// ); + /// + /// if let Ok(slate) = result { + /// // Send slate somehow + /// // ... + /// // Lock our outputs if we're happy the slate was (or is being) sent + /// api_owner.tx_lock_outputs(&slate); + /// } + /// ``` + pub fn tx_lock_outputs(&self, slate: &Slate) -> Result<(), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; @@ -675,38 +650,117 @@ where res } - /// Sender finalization of the transaction. Takes the file returned by the - /// sender as well as the private file generate on the first send step. - /// Builds the complete transaction and sends it to a grin node for - /// propagation. - pub fn finalize_tx(&self, slate: &mut Slate) -> Result<(), Error> { + /// Finalizes a transaction, after all parties + /// have filled in both rounds of Slate generation. This step adds + /// all participants partial signatures to create the final signature, + /// resulting in a final transaction that is ready to post to a node. + /// + /// Note that this function DOES NOT POST the transaction to a node + /// for validation. This is done in separately via the + /// [`post_tx`](struct.Owner.html#method.post_tx) function. + /// + /// This function also stores the final transaction in the user's wallet files for retrieval + /// via the [`get_stored_tx`](struct.Owner.html#method.get_stored_tx) function. + /// + /// # Arguments + /// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). All + /// participants must have filled in both rounds, and the sender should have locked their + /// outputs (via the [`tx_lock_outputs`](struct.Owner.html#method.tx_lock_outputs) function). + /// + /// # Returns + /// * `Ok(())` if successful + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let mut api_owner = Owner::new(wallet.clone()); + /// let amount = 2_000_000_000; + /// + /// // Attempt to create a transaction using the 'default' account + /// let result = api_owner.initiate_tx( + /// None, + /// amount, // amount + /// 10, // minimum confirmations + /// 500, // max outputs + /// 1, // num change outputs + /// true, // select all outputs + /// Some("Finalize this tx now".to_owned()), + /// None, // Use the default slate version + /// ); + /// + /// if let Ok(slate) = result { + /// // Send slate somehow + /// // ... + /// // Lock our outputs if we're happy the slate was (or is being) sent + /// let res = api_owner.tx_lock_outputs(&slate); + /// // + /// // Retrieve slate back from recipient + /// // + /// let res = api_owner.finalize_tx(&slate); + /// } + /// ``` + + pub fn finalize_tx(&self, slate: &Slate) -> Result { let mut w = self.wallet.lock(); + let mut slate = slate.clone(); w.open_with_credentials()?; - let res = owner::finalize_tx(&mut *w, slate); + slate = owner::finalize_tx(&mut *w, &slate)?; w.close()?; - res + Ok(slate) } - /// Roll back a transaction and all associated outputs with a given - /// transaction id This means delete all change outputs, (or recipient - /// output if you're recipient), and unlock all locked outputs associated - /// with the transaction used when a transaction is created but never - /// posted - pub fn cancel_tx(&self, tx_id: Option, tx_slate_id: Option) -> Result<(), Error> { - let mut w = self.wallet.lock(); - w.open_with_credentials()?; - let res = owner::cancel_tx(&mut *w, tx_id, tx_slate_id); - w.close()?; - res - } + /// Posts a completed transaction to the listening node for validation and inclusion in a block + /// for mining. + /// + /// # Arguments + /// * `tx` - A completed [`Transaction`](../grin_core/core/transaction/struct.Transaction.html), + /// typically the `tx` field in the transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). + /// + /// * `fluff` - Instruct the node whether to use the Dandelion protocol when posting the + /// transaction. If `true`, the node should skip the Dandelion phase and broadcast the + /// transaction to all peers immediately. If `false`, the node will follow dandelion logic and + /// initiate the stem phase. + /// + /// # Returns + /// * `Ok(())` if successful + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let mut api_owner = Owner::new(wallet.clone()); + /// let amount = 2_000_000_000; + /// + /// // Attempt to create a transaction using the 'default' account + /// let result = api_owner.initiate_tx( + /// None, + /// amount, // amount + /// 10, // minimum confirmations + /// 500, // max outputs + /// 1, // num change outputs + /// true, // select all outputs + /// Some("Finalize this tx now".to_owned()), + /// None, // Use the default slate version + /// ); + /// + /// if let Ok(slate) = result { + /// // Send slate somehow + /// // ... + /// // Lock our outputs if we're happy the slate was (or is being) sent + /// let res = api_owner.tx_lock_outputs(&slate); + /// // + /// // Retrieve slate back from recipient + /// // + /// let res = api_owner.finalize_tx(&slate); + /// let res = api_owner.post_tx(&slate.tx, true); + /// } + /// ``` - /// Retrieves a stored transaction from a TxLogEntry - pub fn get_stored_tx(&self, entry: &TxLogEntry) -> Result, Error> { - let w = self.wallet.lock(); - owner::get_stored_tx(&*w, entry) - } - - /// Posts a transaction to the chain pub fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), Error> { let client = { let mut w = self.wallet.lock(); @@ -715,12 +769,150 @@ where owner::post_tx(&client, tx, fluff) } - /// Verifies all messages in the slate match their public keys + /// Cancels a transaction. This entails: + /// * Setting the transaction status to either `TxSentCancelled` or `TxReceivedCancelled` + /// * Deleting all change outputs or recipient outputs associated with the transaction + /// * Setting the status of all assocatied inputs from `Locked` to `Spent` so they can be + /// used in new transactions. + /// + /// Transactions can be cancelled by transaction log id or slate id (call with either set to + /// Some, not both) + /// + /// # Arguments + /// + /// * `tx_id` - If present, cancel by the [`TxLogEntry`](../grin_wallet_libwallet/types/struct.TxLogEntry.html) id + /// for the transaction. + /// + /// * `tx_slate_id` - If present, cancel by the Slate id. + /// + /// # Returns + /// * `Ok(())` if successful + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let mut api_owner = Owner::new(wallet.clone()); + /// let amount = 2_000_000_000; + /// + /// // Attempt to create a transaction using the 'default' account + /// let result = api_owner.initiate_tx( + /// None, + /// amount, // amount + /// 10, // minimum confirmations + /// 500, // max outputs + /// 1, // num change outputs + /// true, // select all outputs + /// Some("Cancel this tx".to_owned()), + /// None, // Use the default slate version + /// ); + /// + /// if let Ok(slate) = result { + /// // Send slate somehow + /// // ... + /// // Lock our outputs if we're happy the slate was (or is being) sent + /// let res = api_owner.tx_lock_outputs(&slate); + /// // + /// // We didn't get the slate back, or something else went wrong + /// // + /// let res = api_owner.cancel_tx(None, Some(slate.id.clone())); + /// } + /// ``` + + pub fn cancel_tx(&self, tx_id: Option, tx_slate_id: Option) -> Result<(), Error> { + let mut w = self.wallet.lock(); + w.open_with_credentials()?; + let res = owner::cancel_tx(&mut *w, tx_id, tx_slate_id); + w.close()?; + res + } + + /// Retrieves the stored transaction associated with a TxLogEntry. Can be used even after the + /// transaction has completed. + /// + /// # Arguments + /// + /// * `tx_log_entry` - A [`TxLogEntry`](../grin_wallet_libwallet/types/struct.TxLogEntry.html) + /// + /// # Returns + /// * Ok with the stored [`Transaction`](../grin_core/core/transaction/struct.Transaction.html) + /// if successful + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let api_owner = Owner::new(wallet.clone()); + /// let update_from_node = true; + /// let tx_id = None; + /// let tx_slate_id = None; + /// + /// // Return all TxLogEntries + /// let result = api_owner.retrieve_txs(update_from_node, tx_id, tx_slate_id); + /// + /// if let Ok((was_updated, tx_log_entries)) = result { + /// let stored_tx = api_owner.get_stored_tx(&tx_log_entries[0]).unwrap(); + /// //... + /// } + /// ``` + + // TODO: Should be accepting an id, not an entire entry struct + pub fn get_stored_tx(&self, tx_log_entry: &TxLogEntry) -> Result, Error> { + let w = self.wallet.lock(); + owner::get_stored_tx(&*w, tx_log_entry) + } + + /// Verifies all messages in the slate match their public keys. + /// + /// # Arguments + /// + /// * `slate` - The transaction [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html). + /// + /// # Returns + /// * Ok(()) if successful and the signatures validate + /// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered. + /// + /// # Example + /// Set up as in [`new`](struct.Owner.html#method.new) method above. + /// ``` + /// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config); + /// + /// let mut api_owner = Owner::new(wallet.clone()); + /// let amount = 2_000_000_000; + /// + /// // Attempt to create a transaction using the 'default' account + /// let result = api_owner.initiate_tx( + /// None, + /// amount, // amount + /// 10, // minimum confirmations + /// 500, // max outputs + /// 1, // num change outputs + /// true, // select all outputs + /// Some("Finalize this tx now".to_owned()), + /// None, // Use the default slate version + /// ); + /// + /// if let Ok(slate) = result { + /// // Send slate somehow + /// // ... + /// // Lock our outputs if we're happy the slate was (or is being) sent + /// let res = api_owner.tx_lock_outputs(&slate); + /// // + /// // Retrieve slate back from recipient + /// // + /// let res = api_owner.verify_slate_messages(&slate); + /// } + /// ``` pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error> { owner::verify_slate_messages(slate) } /// Attempt to restore contents of wallet + /// TODO: Full docs pub fn restore(&self) -> Result<(), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; @@ -730,6 +922,7 @@ where } /// Attempt to check and fix the contents of the wallet + /// TODO: Full docs pub fn check_repair(&self, delete_unconfirmed: bool) -> Result<(), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; @@ -739,6 +932,7 @@ where } /// Retrieve current height from node + // TODO: Should return u64 as string pub fn node_height(&self) -> Result<(u64, bool), Error> { let mut w = self.wallet.lock(); w.open_with_credentials()?; @@ -747,3 +941,42 @@ where res } } + +#[doc(hidden)] +#[macro_export] +macro_rules! doctest_helper_setup_doc_env { + ($wallet:ident, $wallet_config:ident) => { + use grin_keychain as keychain; + use grin_util as util; + use grin_wallet_api as api; + use grin_wallet_config as config; + use grin_wallet_impls as impls; + use grin_wallet_libwallet as libwallet; + + use keychain::ExtKeychain; + use tempfile::tempdir; + + use std::sync::Arc; + use util::Mutex; + + use api::Owner; + use config::WalletConfig; + use impls::{HTTPNodeClient, LMDBBackend, WalletSeed}; + use libwallet::types::WalletBackend; + + let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap(); + let dir = dir + .path() + .to_str() + .ok_or("Failed to convert tmpdir path to string.".to_owned()) + .unwrap(); + let mut wallet_config = WalletConfig::default(); + wallet_config.data_file_dir = dir.to_owned(); + let pw = ""; + + let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); + let mut $wallet: Arc>> = Arc::new( + Mutex::new(LMDBBackend::new(wallet_config.clone(), pw, node_client).unwrap()), + ); + }; +} diff --git a/api/src/owner_rpc.rs b/api/src/owner_rpc.rs index a7fb5fb4..1d4b2ae7 100644 --- a/api/src/owner_rpc.rs +++ b/api/src/owner_rpc.rs @@ -13,17 +13,16 @@ // limitations under the License. //! JSON-RPC Stub generation for the Owner API - use uuid::Uuid; use crate::core::core::Transaction; use crate::keychain::{Identifier, Keychain}; use crate::libwallet::slate::Slate; use crate::libwallet::types::{ - AcctPathMapping, NodeClient, OutputData, TxLogEntry, WalletBackend, WalletInfo, + AcctPathMapping, NodeClient, OutputCommitMapping, TxEstimation, TxLogEntry, WalletBackend, + WalletInfo, }; -use crate::libwallet::ErrorKind; -use crate::util::secp::pedersen; +use crate::libwallet::{api_impl, ErrorKind}; use crate::Owner; use easy_jsonrpc; @@ -37,12 +36,16 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "accounts", "params": [], "id": 1 - }, + } + # "# + # , + # r#" { "jsonrpc": "2.0", "result": { @@ -55,7 +58,8 @@ pub trait OwnerRpc { }, "id": 1 } - # ); + # "# + # , 4, false, false, false); ``` */ fn accounts(&self) -> Result, ErrorKind>; @@ -67,12 +71,16 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "create_account_path", "params": ["account1"], "id": 1 - }, + } + # "# + # , + # r#" { "jsonrpc": "2.0", "result": { @@ -80,7 +88,8 @@ pub trait OwnerRpc { }, "id": 1 } - # ); + # "# + # ,4, false, false, false); ``` */ fn create_account_path(&self, label: &String) -> Result; @@ -92,12 +101,16 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "set_active_account", "params": ["default"], "id": 1 - }, + } + # "# + # , + # r#" { "jsonrpc": "2.0", "result": { @@ -105,7 +118,8 @@ pub trait OwnerRpc { }, "id": 1 } - # ); + # "# + # , 4, false, false, false); ``` */ fn set_active_account(&self, label: &String) -> Result<(), ErrorKind>; @@ -113,58 +127,139 @@ pub trait OwnerRpc { /** Networked version of [Owner::retrieve_outputs](struct.Owner.html#method.retrieve_outputs). + # Json rpc example ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "retrieve_outputs", - "params": [false, false, null], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, + "params": [false, true, null], "id": 1 } - # ); + # "# + # , + # r#" + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "Ok": [ + true, + [ + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "output": { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "height": "1", + "is_coinbase": true, + "key_id": "0300000000000000000000000000000000", + "lock_height": "4", + "mmr_index": null, + "n_child": 0, + "root_key_id": "0200000000000000000000000000000000", + "status": "Unspent", + "tx_log_entry": 0, + "value": "60000000000" + } + }, + { + "commit": "087df32304c5d4ae8b2af0bc31e700019d722910ef87dd4eec3197b80b207e3045", + "output": { + "commit": "087df32304c5d4ae8b2af0bc31e700019d722910ef87dd4eec3197b80b207e3045", + "height": "2", + "is_coinbase": true, + "key_id": "0300000000000000000000000100000000", + "lock_height": "5", + "mmr_index": null, + "n_child": 1, + "root_key_id": "0200000000000000000000000000000000", + "status": "Unspent", + "tx_log_entry": 1, + "value": "60000000000" + } + } + ] + ] + } + } + # "# + # , 2, false, false, false); ``` - */ + */ fn retrieve_outputs( &self, include_spent: bool, refresh_from_node: bool, tx_id: Option, - ) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), ErrorKind>; + ) -> Result<(bool, Vec), ErrorKind>; /** Networked version of [Owner::retrieve_txs](struct.Owner.html#method.retrieve_txs). + # Json rpc example ``` - # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( - { + # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" + { + "jsonrpc": "2.0", + "method": "retrieve_txs", + "params": [true, null, null], + "id": 1 + } + # "# + # , + # r#" + { + "id": 1, "jsonrpc": "2.0", - "method": "retrieve_txs", - "params": [false, null, null], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Err": { - "CallbackImpl": "Error opening wallet" + "result": { + "Ok": [ + true, + [ + { + "amount_credited": "60000000000", + "amount_debited": "0", + "confirmation_ts": "2019-01-15T16:01:26Z", + "confirmed": true, + "creation_ts": "2019-01-15T16:01:26Z", + "fee": null, + "id": 0, + "messages": null, + "num_inputs": 0, + "num_outputs": 1, + "parent_key_id": "0200000000000000000000000000000000", + "stored_tx": null, + "tx_slate_id": null, + "tx_type": "ConfirmedCoinbase" + }, + { + "amount_credited": "60000000000", + "amount_debited": "0", + "confirmation_ts": "2019-01-15T16:01:26Z", + "confirmed": true, + "creation_ts": "2019-01-15T16:01:26Z", + "fee": null, + "id": 1, + "messages": null, + "num_inputs": 0, + "num_outputs": 1, + "parent_key_id": "0200000000000000000000000000000000", + "stored_tx": null, + "tx_slate_id": null, + "tx_type": "ConfirmedCoinbase" } - }, - "id": 1 + ] + ] + } } - # ); + # "# + # , 2, false, false, false); ``` - */ + */ + fn retrieve_txs( &self, refresh_from_node: bool, @@ -175,27 +270,42 @@ pub trait OwnerRpc { /** Networked version of [Owner::retrieve_summary_info](struct.Owner.html#method.retrieve_summary_info). - ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "retrieve_summary_info", - "params": [false, 1], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, + "params": [true, 1], "id": 1 } - # ); + # "# + # , + # r#" + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "Ok": [ + true, + { + "amount_awaiting_confirmation": "0", + "amount_awaiting_finalization": "0", + "amount_currently_spendable": "60000000000", + "amount_immature": "180000000000", + "amount_locked": "0", + "last_confirmed_height": "4", + "minimum_confirmations": "1", + "total": "240000000000" + } + ] + } + } + # "# + # ,4, false, false, false); ``` */ + fn retrieve_summary_info( &self, refresh_from_node: bool, @@ -203,28 +313,80 @@ pub trait OwnerRpc { ) -> Result<(bool, WalletInfo), ErrorKind>; /** - Networked version of [Owner::estimate_initiate_tx](struct.Owner.html#method.initiate_tx). + Networked version of [Owner::estimate_initiate_tx](struct.Owner.html#method.initiate_tx). ``` - # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( - { - "jsonrpc": "2.0", - "method": "initiate_tx", - "params": [null, 0, 0, 10, 0, false, "my message", null], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Err": { - "CallbackImpl": "Error opening wallet" + # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" + { + "jsonrpc": "2.0", + "method": "initiate_tx", + "params": [null, 6000000000, 2, 500, 1, true, "my message", null], + "id": 1 + } + # "# + # , + # r#" + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "Ok": { + "amount": "6000000000", + "fee": "8000000", + "height": "4", + "id": "0436430c-2b02-624c-2032-570501212b00", + "lock_height": "0", + "num_participants": 2, + "participant_data": [ + { + "id": "0", + "message": "my message", + "message_sig": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f756f655333250204644c1cb169e7a78f21b57437930db91e808f39be58134c1d", + "part_sig": null, + "public_blind_excess": "034b4df2f0558b73ea72a1ca5c4ab20217c66bbe0829056fca7abe76888e9349ee", + "public_nonce": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" } - }, - "id": 1 + ], + "tx": { + "body": { + "inputs": [ + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "features": "Coinbase" + } + ], + "kernels": [ + { + "excess": "000000000000000000000000000000000000000000000000000000000000000000", + "excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "features": "Plain", + "fee": "8000000", + "lock_height": "0" + } + ], + "outputs": [ + { + "commit": "094be57c91787fc2033d5d97fae099f1a6ddb37ea48370f1a138f09524c767fdd3", + "features": "Plain", + "proof": "2a42e9e902b70ce44e1fccb14de87ee0a97100bddf12c6bead1b9c5f4eb60300f29c13094fa12ffeee238fb4532b18f6b61cf51b23c1c7e1ad2e41560dc27edc0a2b9e647a0b3e4e806fced5b65e61d0f1f5197d3e2285c632d359e27b6b9206b2caffea4f67e0c7a2812e7a22c134b98cf89bd43d9f28b8bec25cce037a0ac5b1ae8f667e54e1250813a5263004486b4465ad4e641ab2b535736ea26535a11013564f08f483b7dab1c2bcc3ee38eadf2f7850eff7e3459a4bbabf9f0cf6c50d0c0a4120565cd4a2ce3e354c11721cd695760a24c70e0d5a0dfc3c5dcd51dfad6de2c237a682f36dc0b271f21bb3655e5333016aaa42c2efa1446e5f3c0a79ec417c4d30f77556951cb0f05dbfafb82d9f95951a9ea241fda2a6388f73ace036b98acce079f0e4feebccc96290a86dcc89118a901210b245f2d114cf94396e4dbb461e82aa26a0581389707957968c7cdc466213bb1cd417db207ef40c05842ab67a01a9b96eb1430ebc26e795bb491258d326d5174ad549401059e41782121e506744af8af9d8e493644a87d613600888541cbbe538c625883f3eb4aa3102c5cfcc25de8e97af8927619ce6a731b3b8462d51d993066b935b0648d2344ad72e4fd70f347fbd81041042e5ea31cc7b2e3156a920b80ecba487b950ca32ca95fae85b759c936246ecf441a9fdd95e8fee932d6782cdec686064018c857efc47fb4b2a122600d5fdd79af2486f44df7e629184e1c573bc0a9b3feb40b190ef2861a1ab45e2ac2201b9cd42e495deea247269820ed32389a2810ad6c0f9a296d2a2d9c54089fed50b7f5ecfcd33ab9954360e1d7f5598c32128cfcf2a1d8bf14616818da8a5343bfa88f0eedf392e9d4ab1ace1b60324129cd4852c2e27813a9cf71a6ae6229a4fcecc1a756b3e664c5f50af333082616815a3bec8fc0b75b8e4e767d719" + } + ] + }, + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000" + }, + "version_info": { + "min_compat_version": 0, + "orig_version": 2, + "version": 2 + } + } + } } - # ); + # "# + # ,4, false, false, false); ``` - */ + */ fn initiate_tx( &self, @@ -244,22 +406,28 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "estimate_initiate_tx", - "params": [null, 0, 0, 10, 0, false], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, + "params": [null, 6000000000, 2, 500, 1, true], "id": 1 } - # ); + # "# + # , + # r#" + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "Ok": { + "total": "60000000000", + "fee": "8000000" + } + } + } + # "# + # ,4, false, false, false); ``` */ fn estimate_initiate_tx( @@ -270,7 +438,7 @@ pub trait OwnerRpc { max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, - ) -> Result<(/* total */ u64, /* fee */ u64), ErrorKind>; + ) -> Result; /** Networked version of [Owner::tx_lock_outputs](struct.Owner.html#method.tx_lock_outputs). @@ -278,43 +446,76 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "tx_lock_outputs", - "params": [{ - "version_info": { - "version": 2, - "orig_version": 2, - "min_compat_version": 0 - }, - "amount": 0, - "fee": 0, - "height": 0, - "id": "414bad48-3386-4fa7-8483-72384c886ba3", - "lock_height": 0, - "num_participants": 2, - "participant_data": [], - "tx": { - "body": { - "inputs": [], - "kernels": [], - "outputs": [] + "id": 1, + "params": [ { + "amount": "6000000000", + "fee": "8000000", + "height": "4", + "id": "0436430c-2b02-624c-2032-570501212b00", + "lock_height": "4", + "num_participants": 2, + "participant_data": [ + { + "id": "0", + "message": "my message", + "message_sig": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f756f655333250204644c1cb169e7a78f21b57437930db91e808f39be58134c1d", + "part_sig": null, + "public_blind_excess": "034b4df2f0558b73ea72a1ca5c4ab20217c66bbe0829056fca7abe76888e9349ee", + "public_nonce": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" + } + ], + "tx": { + "body": { + "inputs": [ + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "features": "Coinbase" + } + ], + "kernels": [ + { + "excess": "000000000000000000000000000000000000000000000000000000000000000000", + "excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "features": "HeightLocked", + "fee": "8000000", + "lock_height": "4" + } + ], + "outputs": [ + { + "commit": "094be57c91787fc2033d5d97fae099f1a6ddb37ea48370f1a138f09524c767fdd3", + "features": "Plain", + "proof": "2a42e9e902b70ce44e1fccb14de87ee0a97100bddf12c6bead1b9c5f4eb60300f29c13094fa12ffeee238fb4532b18f6b61cf51b23c1c7e1ad2e41560dc27edc0a2b9e647a0b3e4e806fced5b65e61d0f1f5197d3e2285c632d359e27b6b9206b2caffea4f67e0c7a2812e7a22c134b98cf89bd43d9f28b8bec25cce037a0ac5b1ae8f667e54e1250813a5263004486b4465ad4e641ab2b535736ea26535a11013564f08f483b7dab1c2bcc3ee38eadf2f7850eff7e3459a4bbabf9f0cf6c50d0c0a4120565cd4a2ce3e354c11721cd695760a24c70e0d5a0dfc3c5dcd51dfad6de2c237a682f36dc0b271f21bb3655e5333016aaa42c2efa1446e5f3c0a79ec417c4d30f77556951cb0f05dbfafb82d9f95951a9ea241fda2a6388f73ace036b98acce079f0e4feebccc96290a86dcc89118a901210b245f2d114cf94396e4dbb461e82aa26a0581389707957968c7cdc466213bb1cd417db207ef40c05842ab67a01a9b96eb1430ebc26e795bb491258d326d5174ad549401059e41782121e506744af8af9d8e493644a87d613600888541cbbe538c625883f3eb4aa3102c5cfcc25de8e97af8927619ce6a731b3b8462d51d993066b935b0648d2344ad72e4fd70f347fbd81041042e5ea31cc7b2e3156a920b80ecba487b950ca32ca95fae85b759c936246ecf441a9fdd95e8fee932d6782cdec686064018c857efc47fb4b2a122600d5fdd79af2486f44df7e629184e1c573bc0a9b3feb40b190ef2861a1ab45e2ac2201b9cd42e495deea247269820ed32389a2810ad6c0f9a296d2a2d9c54089fed50b7f5ecfcd33ab9954360e1d7f5598c32128cfcf2a1d8bf14616818da8a5343bfa88f0eedf392e9d4ab1ace1b60324129cd4852c2e27813a9cf71a6ae6229a4fcecc1a756b3e664c5f50af333082616815a3bec8fc0b75b8e4e767d719" + } + ] + }, + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000" }, - "offset": "0000000000000000000000000000000000000000000000000000000000000000" + "version_info": { + "min_compat_version": 0, + "orig_version": 2, + "version": 2 + } } - }], - "id": 1 - }, + ] + } + # "# + # , + # r#" { "jsonrpc": "2.0", + "id": 1, "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, - "id": 1 + "Ok": null + } } - # ); + # "# + # ,5 ,true, false, false); + ``` */ fn tx_lock_outputs(&self, slate: Slate) -> Result<(), ErrorKind>; @@ -322,72 +523,257 @@ pub trait OwnerRpc { /** Networked version of [Owner::finalize_tx](struct.Owner.html#method.finalize_tx). - ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "finalize_tx", - "params": [{ + "id": 1, + "params": [ + { "version_info": { "version": 2, "orig_version": 2, "min_compat_version": 0 }, - "amount": 0, - "fee": 0, - "height": 0, - "id": "414bad48-3386-4fa7-8483-72384c886ba3", - "lock_height": 0, "num_participants": 2, - "participant_data": [], + "id": "0436430c-2b02-624c-2032-570501212b00", "tx": { + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000", "body": { - "inputs": [], - "kernels": [], - "outputs": [] + "inputs": [ + { + "features": "Coinbase", + "commit": "087df32304c5d4ae8b2af0bc31e700019d722910ef87dd4eec3197b80b207e3045" + }, + { + "features": "Coinbase", + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7" + } + ], + "outputs": [ + { + "features": "Plain", + "commit": "099b48cfb1f80a2347dc89818449e68e76a3c6817a532a8e9ef2b4a5ccf4363850", + "proof": "7ebcd2ed9bf5fb29854033ba3d0e720613bdf7dfacc586d2f6084c1cde0a2b72e955d4ce625916701dc7c347132f40d0f102a34e801d745ee54b49b765d08aae0bb801c60403e57cafade3b4b174e795b633ab9e402b5b1b6e1243fd10bbcf9368a75cb6a6c375c7bdf02da9e03b7f210df45d942e6fba2729cd512a372e6ed91a1b5c9c22831febea843e3f85adcf198f39ac9f7b73b70c60bfb474aa69878ea8d1d32fef30166b59caacaec3fd024de29a90f1587e08d2c36b3d5c560cabf658e212e0a40a4129b3e5c35557058def5551f4eb395759597ba808b3c34eac3bfb9716e4480d7931c5789c538463ec75be0eb807c894047fda6cbcd22682d3c6d3823cb330f090a2099e3510a3706b57d46c95224394d7f1c0a20d99cc314b8f1d9d02668e2e435f62e1194de0be6a1f50f72ed777ed51c8819f527a94918d1aa8df6461e98ed4c2b18210de50fbcf8c3df210bfe326d41f1dc0ad748cb0320ae28401c85ab4f7dcb99d88a052e95dc85b76d22b36cabd60e06ab84bb7e4ddfdab9c9730c8a986583237ed1ecbb323ee8e79b8cadca4b438b7c09531670b471dda6a2eb3e747916c88ce7d9d8e1b7f61660eeb9e5a13c60e4dfe89d1177d81d6f6570fda85158e646a15f1e8b9e977494dc19a339aab2e0e478670d80092d6ba37646e60714ef64eb4a3d37fe15f8f38b59114af34b235489eed3f69b7781c5fe496eb43ffe245c14bd740f745844a38cf0d904347aaa2b64f51add18822dac009d8b63fa3e4c9b1fa72187f9a4acba1ab315daa1b04c9a41f3be846ac420b37990e6c947a16cc9d5c0671b292bf77d7d8b8974d2ad3afae95ba7772c37432840f53a007f31e0195f3abdf100c4477723cc6c6d5da14894a73dfac342833731036487488fdade7b9d556c06f26173b6b67598d3769447ce2828d71dd45ac5af436c6b0" + }, + { + "features": "Plain", + "commit": "0812276cc788e6870612296d926cba9f0e7b9810670710b5a6e6f1ba006d395774", + "proof": "dcff6175390c602bfa92c2ffd1a9b2d84dcc9ea941f6f317bdd0f875244ef23e696fd17c71df79760ce5ce1a96aab1d15dd057358dc835e972febeb86d50ccec0dad7cfe0246d742eb753cf7b88c045d15bc7123f8cf7155647ccf663fca92a83c9a65d0ed756ea7ebffd2cac90c380a102ed9caaa355d175ed0bf58d3ac2f5e909d6c447dfc6b605e04925c2b17c33ebd1908c965a5541ea5d2ed45a0958e6402f89d7a56df1992e036d836e74017e73ccad5cb3a82b8e139e309792a31b15f3ffd72ed033253428c156c2b9799458a25c1da65b719780a22de7fe7f437ae2fccd22cf7ea357ab5aa66a5ef7d71fb0dc64aa0b5761f68278062bb39bb296c787e4cabc5e2a2933a416ce1c9a9696160386449c437e9120f7bb26e5b0e74d1f2e7d5bcd7aafb2a92b87d1548f1f911fb06af7bd6cc13cee29f7c9cb79021aed18186272af0e9d189ec107c81a8a3aeb4782b0d950e4881aa51b776bb6844b25bce97035b48a9bdb2aea3608687bcdd479d4fa998b5a839ff88558e4a29dff0ed13b55900abb5d439b70793d902ae9ad34587b18c919f6b875c91d14deeb1c373f5e76570d59a6549758f655f1128a54f162dfe8868e1587028e26ad91e528c5ae7ee9335fa58fb59022b5de29d80f0764a9917390d46db899acc6a5b416e25ecc9dccb7153646addcc81cadb5f0078febc7e05d7735aba494f39ef05697bbcc9b47b2ccc79595d75fc13c80678b5e237edce58d731f34c05b1ddcaa649acf2d865bbbc3ceda10508bcdd29d0496744644bf1c3516f6687dfeef5649c7dff90627d642739a59d91a8d1d0c4dc55d74a949e1074427664b467992c9e0f7d3af9d6ea79513e8946ddc0d356bac49878e64e6a95b0a30214214faf2ce317fa622ff3266b32a816e10a18e6d789a5da1f23e67b4f970a68a7bcd9e18825ee274b0483896a40" + } + ], + "kernels": [ + { + "features": "HeightLocked", + "fee": "7000000", + "lock_height": "5", + "excess": "000000000000000000000000000000000000000000000000000000000000000000", + "excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ] + } + }, + "amount": "60000000000", + "fee": "7000000", + "height": "5", + "lock_height": "5", + "participant_data": [ + { + "id": "0", + "public_blind_excess": "033ac2158fa0077f087de60c19d8e431753baa5b63b6e1477f05a2a6e7190d4592", + "public_nonce": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "part_sig": null, + "message": null, + "message_sig": null }, - "offset": "0000000000000000000000000000000000000000000000000000000000000000" - } - }], - "id": 1 - }, + { + "id": "1", + "public_blind_excess": "024f9bc78c984c78d6e916d3a00746aa30fa1172124c8dbc0cbddcb7b486719bc7", + "public_nonce": "0292a0baa95464d44b2c7155c7e2c69213bd3737f6217e60273af159b7f49812e3", + "part_sig": "92a0baa95464d44b2c7155c7e2c69213bd3737f6217e60273af159b7f49812e30d5ef73628c7de327a40dbc943ca227ab809b8edf954b18b69a4f9b333e7278c", + "message": null, + "message_sig": null + } + ] + } + ] + } + # "# + # , + # r#" { "jsonrpc": "2.0", + "id": 1, "result": { - "Err": { - "CallbackImpl": "Error opening wallet" + "Ok": { + "amount": "60000000000", + "fee": "7000000", + "height": "5", + "id": "0436430c-2b02-624c-2032-570501212b00", + "lock_height": "5", + "num_participants": 2, + "participant_data": [ + { + "id": "0", + "message": null, + "message_sig": null, + "part_sig": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f3127d36e8cc35aa76091a491e94fcffdd2f25d70d23e698ece2d8db14334670a", + "public_blind_excess": "033ac2158fa0077f087de60c19d8e431753baa5b63b6e1477f05a2a6e7190d4592", + "public_nonce": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" + }, + { + "id": "1", + "message": null, + "message_sig": null, + "part_sig": "92a0baa95464d44b2c7155c7e2c69213bd3737f6217e60273af159b7f49812e30d5ef73628c7de327a40dbc943ca227ab809b8edf954b18b69a4f9b333e7278c", + "public_blind_excess": "024f9bc78c984c78d6e916d3a00746aa30fa1172124c8dbc0cbddcb7b486719bc7", + "public_nonce": "0292a0baa95464d44b2c7155c7e2c69213bd3737f6217e60273af159b7f49812e3" + } + ], + "tx": { + "body": { + "inputs": [ + { + "commit": "087df32304c5d4ae8b2af0bc31e700019d722910ef87dd4eec3197b80b207e3045", + "features": "Coinbase" + }, + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "features": "Coinbase" + } + ], + "kernels": [ + { + "excess": "09bac6083b05a32a9d9b37710c70dd0a1ef9329fde0848558976b6f1b81d80ceed", + "excess_sig": "4a1802e31b854d765bdd7e114cef33b852c3fed01436c50d70d7c662333272683e86caa4b58b38d9dad2805b2d19f2788afc165ecb931b1a37d28764771b8e96", + "features": "HeightLocked", + "fee": "7000000", + "lock_height": "5" + } + ], + "outputs": [ + { + "commit": "099b48cfb1f80a2347dc89818449e68e76a3c6817a532a8e9ef2b4a5ccf4363850", + "features": "Plain", + "proof": "7ebcd2ed9bf5fb29854033ba3d0e720613bdf7dfacc586d2f6084c1cde0a2b72e955d4ce625916701dc7c347132f40d0f102a34e801d745ee54b49b765d08aae0bb801c60403e57cafade3b4b174e795b633ab9e402b5b1b6e1243fd10bbcf9368a75cb6a6c375c7bdf02da9e03b7f210df45d942e6fba2729cd512a372e6ed91a1b5c9c22831febea843e3f85adcf198f39ac9f7b73b70c60bfb474aa69878ea8d1d32fef30166b59caacaec3fd024de29a90f1587e08d2c36b3d5c560cabf658e212e0a40a4129b3e5c35557058def5551f4eb395759597ba808b3c34eac3bfb9716e4480d7931c5789c538463ec75be0eb807c894047fda6cbcd22682d3c6d3823cb330f090a2099e3510a3706b57d46c95224394d7f1c0a20d99cc314b8f1d9d02668e2e435f62e1194de0be6a1f50f72ed777ed51c8819f527a94918d1aa8df6461e98ed4c2b18210de50fbcf8c3df210bfe326d41f1dc0ad748cb0320ae28401c85ab4f7dcb99d88a052e95dc85b76d22b36cabd60e06ab84bb7e4ddfdab9c9730c8a986583237ed1ecbb323ee8e79b8cadca4b438b7c09531670b471dda6a2eb3e747916c88ce7d9d8e1b7f61660eeb9e5a13c60e4dfe89d1177d81d6f6570fda85158e646a15f1e8b9e977494dc19a339aab2e0e478670d80092d6ba37646e60714ef64eb4a3d37fe15f8f38b59114af34b235489eed3f69b7781c5fe496eb43ffe245c14bd740f745844a38cf0d904347aaa2b64f51add18822dac009d8b63fa3e4c9b1fa72187f9a4acba1ab315daa1b04c9a41f3be846ac420b37990e6c947a16cc9d5c0671b292bf77d7d8b8974d2ad3afae95ba7772c37432840f53a007f31e0195f3abdf100c4477723cc6c6d5da14894a73dfac342833731036487488fdade7b9d556c06f26173b6b67598d3769447ce2828d71dd45ac5af436c6b0" + }, + { + "commit": "0812276cc788e6870612296d926cba9f0e7b9810670710b5a6e6f1ba006d395774", + "features": "Plain", + "proof": "dcff6175390c602bfa92c2ffd1a9b2d84dcc9ea941f6f317bdd0f875244ef23e696fd17c71df79760ce5ce1a96aab1d15dd057358dc835e972febeb86d50ccec0dad7cfe0246d742eb753cf7b88c045d15bc7123f8cf7155647ccf663fca92a83c9a65d0ed756ea7ebffd2cac90c380a102ed9caaa355d175ed0bf58d3ac2f5e909d6c447dfc6b605e04925c2b17c33ebd1908c965a5541ea5d2ed45a0958e6402f89d7a56df1992e036d836e74017e73ccad5cb3a82b8e139e309792a31b15f3ffd72ed033253428c156c2b9799458a25c1da65b719780a22de7fe7f437ae2fccd22cf7ea357ab5aa66a5ef7d71fb0dc64aa0b5761f68278062bb39bb296c787e4cabc5e2a2933a416ce1c9a9696160386449c437e9120f7bb26e5b0e74d1f2e7d5bcd7aafb2a92b87d1548f1f911fb06af7bd6cc13cee29f7c9cb79021aed18186272af0e9d189ec107c81a8a3aeb4782b0d950e4881aa51b776bb6844b25bce97035b48a9bdb2aea3608687bcdd479d4fa998b5a839ff88558e4a29dff0ed13b55900abb5d439b70793d902ae9ad34587b18c919f6b875c91d14deeb1c373f5e76570d59a6549758f655f1128a54f162dfe8868e1587028e26ad91e528c5ae7ee9335fa58fb59022b5de29d80f0764a9917390d46db899acc6a5b416e25ecc9dccb7153646addcc81cadb5f0078febc7e05d7735aba494f39ef05697bbcc9b47b2ccc79595d75fc13c80678b5e237edce58d731f34c05b1ddcaa649acf2d865bbbc3ceda10508bcdd29d0496744644bf1c3516f6687dfeef5649c7dff90627d642739a59d91a8d1d0c4dc55d74a949e1074427664b467992c9e0f7d3af9d6ea79513e8946ddc0d356bac49878e64e6a95b0a30214214faf2ce317fa622ff3266b32a816e10a18e6d789a5da1f23e67b4f970a68a7bcd9e18825ee274b0483896a40" + } + ] + }, + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000" + }, + "version_info": { + "min_compat_version": 0, + "orig_version": 2, + "version": 2 + } } - }, - "id": 1 + } } - # ); + # "# + # , 5, true, true, false); ``` */ fn finalize_tx(&self, slate: Slate) -> Result; + /** + Networked version of [Owner::post_tx](struct.Owner.html#method.post_tx). + + ``` + # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" + { + "jsonrpc": "2.0", + "id": 1, + "method": "post_tx", + "params": [ + { + "body": { + "inputs": [ + { + "commit": "087df32304c5d4ae8b2af0bc31e700019d722910ef87dd4eec3197b80b207e3045", + "features": "Coinbase" + }, + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "features": "Coinbase" + } + ], + "kernels": [ + { + "excess": "09bac6083b05a32a9d9b37710c70dd0a1ef9329fde0848558976b6f1b81d80ceed", + "excess_sig": "4a1802e31b854d765bdd7e114cef33b852c3fed01436c50d70d7c662333272683e86caa4b58b38d9dad2805b2d19f2788afc165ecb931b1a37d28764771b8e96", + "features": "HeightLocked", + "fee": "7000000", + "lock_height": "5" + } + ], + "outputs": [ + { + "commit": "099b48cfb1f80a2347dc89818449e68e76a3c6817a532a8e9ef2b4a5ccf4363850", + "features": "Plain", + "proof": "7ebcd2ed9bf5fb29854033ba3d0e720613bdf7dfacc586d2f6084c1cde0a2b72e955d4ce625916701dc7c347132f40d0f102a34e801d745ee54b49b765d08aae0bb801c60403e57cafade3b4b174e795b633ab9e402b5b1b6e1243fd10bbcf9368a75cb6a6c375c7bdf02da9e03b7f210df45d942e6fba2729cd512a372e6ed91a1b5c9c22831febea843e3f85adcf198f39ac9f7b73b70c60bfb474aa69878ea8d1d32fef30166b59caacaec3fd024de29a90f1587e08d2c36b3d5c560cabf658e212e0a40a4129b3e5c35557058def5551f4eb395759597ba808b3c34eac3bfb9716e4480d7931c5789c538463ec75be0eb807c894047fda6cbcd22682d3c6d3823cb330f090a2099e3510a3706b57d46c95224394d7f1c0a20d99cc314b8f1d9d02668e2e435f62e1194de0be6a1f50f72ed777ed51c8819f527a94918d1aa8df6461e98ed4c2b18210de50fbcf8c3df210bfe326d41f1dc0ad748cb0320ae28401c85ab4f7dcb99d88a052e95dc85b76d22b36cabd60e06ab84bb7e4ddfdab9c9730c8a986583237ed1ecbb323ee8e79b8cadca4b438b7c09531670b471dda6a2eb3e747916c88ce7d9d8e1b7f61660eeb9e5a13c60e4dfe89d1177d81d6f6570fda85158e646a15f1e8b9e977494dc19a339aab2e0e478670d80092d6ba37646e60714ef64eb4a3d37fe15f8f38b59114af34b235489eed3f69b7781c5fe496eb43ffe245c14bd740f745844a38cf0d904347aaa2b64f51add18822dac009d8b63fa3e4c9b1fa72187f9a4acba1ab315daa1b04c9a41f3be846ac420b37990e6c947a16cc9d5c0671b292bf77d7d8b8974d2ad3afae95ba7772c37432840f53a007f31e0195f3abdf100c4477723cc6c6d5da14894a73dfac342833731036487488fdade7b9d556c06f26173b6b67598d3769447ce2828d71dd45ac5af436c6b0" + }, + { + "commit": "0812276cc788e6870612296d926cba9f0e7b9810670710b5a6e6f1ba006d395774", + "features": "Plain", + "proof": "dcff6175390c602bfa92c2ffd1a9b2d84dcc9ea941f6f317bdd0f875244ef23e696fd17c71df79760ce5ce1a96aab1d15dd057358dc835e972febeb86d50ccec0dad7cfe0246d742eb753cf7b88c045d15bc7123f8cf7155647ccf663fca92a83c9a65d0ed756ea7ebffd2cac90c380a102ed9caaa355d175ed0bf58d3ac2f5e909d6c447dfc6b605e04925c2b17c33ebd1908c965a5541ea5d2ed45a0958e6402f89d7a56df1992e036d836e74017e73ccad5cb3a82b8e139e309792a31b15f3ffd72ed033253428c156c2b9799458a25c1da65b719780a22de7fe7f437ae2fccd22cf7ea357ab5aa66a5ef7d71fb0dc64aa0b5761f68278062bb39bb296c787e4cabc5e2a2933a416ce1c9a9696160386449c437e9120f7bb26e5b0e74d1f2e7d5bcd7aafb2a92b87d1548f1f911fb06af7bd6cc13cee29f7c9cb79021aed18186272af0e9d189ec107c81a8a3aeb4782b0d950e4881aa51b776bb6844b25bce97035b48a9bdb2aea3608687bcdd479d4fa998b5a839ff88558e4a29dff0ed13b55900abb5d439b70793d902ae9ad34587b18c919f6b875c91d14deeb1c373f5e76570d59a6549758f655f1128a54f162dfe8868e1587028e26ad91e528c5ae7ee9335fa58fb59022b5de29d80f0764a9917390d46db899acc6a5b416e25ecc9dccb7153646addcc81cadb5f0078febc7e05d7735aba494f39ef05697bbcc9b47b2ccc79595d75fc13c80678b5e237edce58d731f34c05b1ddcaa649acf2d865bbbc3ceda10508bcdd29d0496744644bf1c3516f6687dfeef5649c7dff90627d642739a59d91a8d1d0c4dc55d74a949e1074427664b467992c9e0f7d3af9d6ea79513e8946ddc0d356bac49878e64e6a95b0a30214214faf2ce317fa622ff3266b32a816e10a18e6d789a5da1f23e67b4f970a68a7bcd9e18825ee274b0483896a40" + } + ] + }, + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000" + }, + false + ] + } + # "# + # , + # r#" + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "Ok": null + } + } + # "# + # , 5, true, true, true); + ``` + */ + + fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), ErrorKind>; + /** Networked version of [Owner::cancel_tx](struct.Owner.html#method.cancel_tx). ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "cancel_tx", - "params": [null, null], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, + "params": [null, "0436430c-2b02-624c-2032-570501212b00"], "id": 1 } - # ); + # "# + # , + # r#" + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "Ok": null + } + } + # "# + # , 5, true, true, false); ``` */ fn cancel_tx(&self, tx_id: Option, tx_slate_id: Option) -> Result<(), ErrorKind>; @@ -395,123 +781,174 @@ pub trait OwnerRpc { /** Networked version of [Owner::get_stored_tx](struct.Owner.html#method.get_stored_tx). - ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "get_stored_tx", + "id": 1, "params": [ { - "amount_credited": 0, - "amount_debited": 0, - "confirmation_ts": null, + "amount_credited": "59993000000", + "amount_debited": "120000000000", + "confirmation_ts": "2019-01-15T16:01:26Z", "confirmed": false, - "creation_ts": "2019-03-05T20:49:59.444095Z", - "fee": null, - "id": 10, - "messages": null, - "num_inputs": 0, - "num_outputs": 0, - "parent_key_id": "0000000000000000000000000000000000", - "stored_tx": null, - "tx_slate_id": null, - "tx_type": "TxReceived" - } - ], - "id": 1 - }, - { - "jsonrpc": "2.0", - "result": { - "Ok": null - }, - "id": 1 - } - # ); - ``` - */ - fn get_stored_tx(&self, entry: &TxLogEntry) -> Result, ErrorKind>; - - /** - Networked version of [Owner::post_tx](struct.Owner.html#method.post_tx). - - ```no_run - # // This test currently fails on travis - # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( - { - "jsonrpc": "2.0", - "method": "post_tx", - "params": [ - { - "body": { - "inputs": [], - "kernels": [], - "outputs": [] + "creation_ts": "2019-01-15T16:01:26Z", + "fee": "7000000", + "id": 5, + "messages": { + "messages": [ + { + "id": "0", + "message": null, + "message_sig": null, + "public_key": "033ac2158fa0077f087de60c19d8e431753baa5b63b6e1477f05a2a6e7190d4592" + }, + { + "id": "1", + "message": null, + "message_sig": null, + "public_key": "024f9bc78c984c78d6e916d3a00746aa30fa1172124c8dbc0cbddcb7b486719bc7" + } + ] }, - "offset": "0000000000000000000000000000000000000000000000000000000000000000" - }, - false - ], - "id": 1 - }, + "num_inputs": 2, + "num_outputs": 1, + "parent_key_id": "0200000000000000000000000000000000", + "stored_tx": "0436430c-2b02-624c-2032-570501212b00.grintx", + "tx_slate_id": "0436430c-2b02-624c-2032-570501212b00", + "tx_type": "TxSent" + } + ] + } + # "# + # , + # r#" { "jsonrpc": "2.0", + "id": 1, "result": { - "Err": { - "ClientCallback": "Posting transaction to node: Request error: Cannot make request: an error occurred trying to connect: Connection refused (os error 61)" + "Ok": { + "body": { + "inputs": [ + { + "commit": "087df32304c5d4ae8b2af0bc31e700019d722910ef87dd4eec3197b80b207e3045", + "features": "Coinbase" + }, + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "features": "Coinbase" + } + ], + "kernels": [ + { + "excess": "000000000000000000000000000000000000000000000000000000000000000000", + "excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "features": "Plain", + "fee": "7000000", + "lock_height": "0" + } + ], + "outputs": [ + { + "commit": "099b48cfb1f80a2347dc89818449e68e76a3c6817a532a8e9ef2b4a5ccf4363850", + "features": "Plain", + "proof": "7ebcd2ed9bf5fb29854033ba3d0e720613bdf7dfacc586d2f6084c1cde0a2b72e955d4ce625916701dc7c347132f40d0f102a34e801d745ee54b49b765d08aae0bb801c60403e57cafade3b4b174e795b633ab9e402b5b1b6e1243fd10bbcf9368a75cb6a6c375c7bdf02da9e03b7f210df45d942e6fba2729cd512a372e6ed91a1b5c9c22831febea843e3f85adcf198f39ac9f7b73b70c60bfb474aa69878ea8d1d32fef30166b59caacaec3fd024de29a90f1587e08d2c36b3d5c560cabf658e212e0a40a4129b3e5c35557058def5551f4eb395759597ba808b3c34eac3bfb9716e4480d7931c5789c538463ec75be0eb807c894047fda6cbcd22682d3c6d3823cb330f090a2099e3510a3706b57d46c95224394d7f1c0a20d99cc314b8f1d9d02668e2e435f62e1194de0be6a1f50f72ed777ed51c8819f527a94918d1aa8df6461e98ed4c2b18210de50fbcf8c3df210bfe326d41f1dc0ad748cb0320ae28401c85ab4f7dcb99d88a052e95dc85b76d22b36cabd60e06ab84bb7e4ddfdab9c9730c8a986583237ed1ecbb323ee8e79b8cadca4b438b7c09531670b471dda6a2eb3e747916c88ce7d9d8e1b7f61660eeb9e5a13c60e4dfe89d1177d81d6f6570fda85158e646a15f1e8b9e977494dc19a339aab2e0e478670d80092d6ba37646e60714ef64eb4a3d37fe15f8f38b59114af34b235489eed3f69b7781c5fe496eb43ffe245c14bd740f745844a38cf0d904347aaa2b64f51add18822dac009d8b63fa3e4c9b1fa72187f9a4acba1ab315daa1b04c9a41f3be846ac420b37990e6c947a16cc9d5c0671b292bf77d7d8b8974d2ad3afae95ba7772c37432840f53a007f31e0195f3abdf100c4477723cc6c6d5da14894a73dfac342833731036487488fdade7b9d556c06f26173b6b67598d3769447ce2828d71dd45ac5af436c6b0" + }, + { + "commit": "0812276cc788e6870612296d926cba9f0e7b9810670710b5a6e6f1ba006d395774", + "features": "Plain", + "proof": "dcff6175390c602bfa92c2ffd1a9b2d84dcc9ea941f6f317bdd0f875244ef23e696fd17c71df79760ce5ce1a96aab1d15dd057358dc835e972febeb86d50ccec0dad7cfe0246d742eb753cf7b88c045d15bc7123f8cf7155647ccf663fca92a83c9a65d0ed756ea7ebffd2cac90c380a102ed9caaa355d175ed0bf58d3ac2f5e909d6c447dfc6b605e04925c2b17c33ebd1908c965a5541ea5d2ed45a0958e6402f89d7a56df1992e036d836e74017e73ccad5cb3a82b8e139e309792a31b15f3ffd72ed033253428c156c2b9799458a25c1da65b719780a22de7fe7f437ae2fccd22cf7ea357ab5aa66a5ef7d71fb0dc64aa0b5761f68278062bb39bb296c787e4cabc5e2a2933a416ce1c9a9696160386449c437e9120f7bb26e5b0e74d1f2e7d5bcd7aafb2a92b87d1548f1f911fb06af7bd6cc13cee29f7c9cb79021aed18186272af0e9d189ec107c81a8a3aeb4782b0d950e4881aa51b776bb6844b25bce97035b48a9bdb2aea3608687bcdd479d4fa998b5a839ff88558e4a29dff0ed13b55900abb5d439b70793d902ae9ad34587b18c919f6b875c91d14deeb1c373f5e76570d59a6549758f655f1128a54f162dfe8868e1587028e26ad91e528c5ae7ee9335fa58fb59022b5de29d80f0764a9917390d46db899acc6a5b416e25ecc9dccb7153646addcc81cadb5f0078febc7e05d7735aba494f39ef05697bbcc9b47b2ccc79595d75fc13c80678b5e237edce58d731f34c05b1ddcaa649acf2d865bbbc3ceda10508bcdd29d0496744644bf1c3516f6687dfeef5649c7dff90627d642739a59d91a8d1d0c4dc55d74a949e1074427664b467992c9e0f7d3af9d6ea79513e8946ddc0d356bac49878e64e6a95b0a30214214faf2ce317fa622ff3266b32a816e10a18e6d789a5da1f23e67b4f970a68a7bcd9e18825ee274b0483896a40" + } + ] + }, + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000" } - }, - "id": 1 + } } - # ); + # "# + # , 5, true, true, false); ``` */ - fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), ErrorKind>; + fn get_stored_tx(&self, tx: &TxLogEntry) -> Result, ErrorKind>; /** Networked version of [Owner::verify_slate_messages](struct.Owner.html#method.verify_slate_messages). - ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "verify_slate_messages", - "params": [{ - "version_info": { - "version": 2, - "orig_version": 2, - "min_compat_version": 0 - }, - "amount": 0, - "fee": 0, - "height": 0, - "id": "414bad48-3386-4fa7-8483-72384c886ba3", - "lock_height": 0, - "num_participants": 2, - "participant_data": [], - "tx": { - "body": { - "inputs": [], - "kernels": [], - "outputs": [] + "id": 1, + "params": [ { + "amount": "6000000000", + "fee": "8000000", + "height": "4", + "id": "0436430c-2b02-624c-2032-570501212b00", + "lock_height": "4", + "num_participants": 2, + "participant_data": [ + { + "id": "0", + "message": "my message", + "message_sig": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f756f655333250204644c1cb169e7a78f21b57437930db91e808f39be58134c1d", + "part_sig": null, + "public_blind_excess": "034b4df2f0558b73ea72a1ca5c4ab20217c66bbe0829056fca7abe76888e9349ee", + "public_nonce": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" + } + ], + "tx": { + "body": { + "inputs": [ + { + "commit": "08e1da9e6dc4d6e808a718b2f110a991dd775d65ce5ae408a4e1f002a4961aa9e7", + "features": "Coinbase" + } + ], + "kernels": [ + { + "excess": "000000000000000000000000000000000000000000000000000000000000000000", + "excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "features": "HeightLocked", + "fee": "8000000", + "lock_height": "4" + } + ], + "outputs": [ + { + "commit": "094be57c91787fc2033d5d97fae099f1a6ddb37ea48370f1a138f09524c767fdd3", + "features": "Plain", + "proof": "2a42e9e902b70ce44e1fccb14de87ee0a97100bddf12c6bead1b9c5f4eb60300f29c13094fa12ffeee238fb4532b18f6b61cf51b23c1c7e1ad2e41560dc27edc0a2b9e647a0b3e4e806fced5b65e61d0f1f5197d3e2285c632d359e27b6b9206b2caffea4f67e0c7a2812e7a22c134b98cf89bd43d9f28b8bec25cce037a0ac5b1ae8f667e54e1250813a5263004486b4465ad4e641ab2b535736ea26535a11013564f08f483b7dab1c2bcc3ee38eadf2f7850eff7e3459a4bbabf9f0cf6c50d0c0a4120565cd4a2ce3e354c11721cd695760a24c70e0d5a0dfc3c5dcd51dfad6de2c237a682f36dc0b271f21bb3655e5333016aaa42c2efa1446e5f3c0a79ec417c4d30f77556951cb0f05dbfafb82d9f95951a9ea241fda2a6388f73ace036b98acce079f0e4feebccc96290a86dcc89118a901210b245f2d114cf94396e4dbb461e82aa26a0581389707957968c7cdc466213bb1cd417db207ef40c05842ab67a01a9b96eb1430ebc26e795bb491258d326d5174ad549401059e41782121e506744af8af9d8e493644a87d613600888541cbbe538c625883f3eb4aa3102c5cfcc25de8e97af8927619ce6a731b3b8462d51d993066b935b0648d2344ad72e4fd70f347fbd81041042e5ea31cc7b2e3156a920b80ecba487b950ca32ca95fae85b759c936246ecf441a9fdd95e8fee932d6782cdec686064018c857efc47fb4b2a122600d5fdd79af2486f44df7e629184e1c573bc0a9b3feb40b190ef2861a1ab45e2ac2201b9cd42e495deea247269820ed32389a2810ad6c0f9a296d2a2d9c54089fed50b7f5ecfcd33ab9954360e1d7f5598c32128cfcf2a1d8bf14616818da8a5343bfa88f0eedf392e9d4ab1ace1b60324129cd4852c2e27813a9cf71a6ae6229a4fcecc1a756b3e664c5f50af333082616815a3bec8fc0b75b8e4e767d719" + } + ] + }, + "offset": "d202964900000000d302964900000000d402964900000000d502964900000000" }, - "offset": "0000000000000000000000000000000000000000000000000000000000000000" + "version_info": { + "min_compat_version": 0, + "orig_version": 2, + "version": 2 + } } - }], - "id": 1 - }, + ] + } + # "# + # , + # r#" { "jsonrpc": "2.0", + "id": 1, "result": { - "Ok": null - }, - "id": 1 + "Ok": null + } } - # ); + # "# + # ,5 ,true, false, false); ``` - */ + */ fn verify_slate_messages(&self, slate: &Slate) -> Result<(), ErrorKind>; /** @@ -520,22 +957,25 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "restore", "params": [], "id": 1 - }, + } + # "# + # , + # r#" { + "id": 1, "jsonrpc": "2.0", "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, - "id": 1 + "Ok": null + } } - # ); + # "# + # , 1, false, false, false); ``` */ fn restore(&self) -> Result<(), ErrorKind>; @@ -546,22 +986,25 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "check_repair", "params": [false], "id": 1 - }, + } + # "# + # , + # r#" { + "id": 1, "jsonrpc": "2.0", "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, - "id": 1 + "Ok": null + } } - # ); + # "# + # , 1, false, false, false); ``` */ fn check_repair(&self, delete_unconfirmed: bool) -> Result<(), ErrorKind>; @@ -572,22 +1015,28 @@ pub trait OwnerRpc { ``` # grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!( + # r#" { "jsonrpc": "2.0", "method": "node_height", "params": [], "id": 1 - }, + } + # "# + # , + # r#" { + "id": 1, "jsonrpc": "2.0", "result": { - "Err": { - "CallbackImpl": "Error opening wallet" - } - }, - "id": 1 + "Ok": [ + 5, + true + ] + } } - # ); + # "# + # , 5, false, false, false); ``` */ fn node_height(&self) -> Result<(u64, bool), ErrorKind>; @@ -616,7 +1065,7 @@ where include_spent: bool, refresh_from_node: bool, tx_id: Option, - ) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), ErrorKind> { + ) -> Result<(bool, Vec), ErrorKind> { Owner::retrieve_outputs(self, include_spent, refresh_from_node, tx_id).map_err(|e| e.kind()) } @@ -671,7 +1120,7 @@ where max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, - ) -> Result<(/* total */ u64, /* fee */ u64), ErrorKind> { + ) -> Result { Owner::estimate_initiate_tx( self, src_acct_name.as_ref().map(String::as_str), @@ -685,8 +1134,7 @@ where } fn finalize_tx(&self, mut slate: Slate) -> Result { - Owner::finalize_tx(self, &mut slate).map_err(|e| e.kind())?; - Ok(slate) + Owner::finalize_tx(self, &mut slate).map_err(|e| e.kind()) } fn tx_lock_outputs(&self, mut slate: Slate) -> Result<(), ErrorKind> { @@ -697,8 +1145,8 @@ where Owner::cancel_tx(self, tx_id, tx_slate_id).map_err(|e| e.kind()) } - fn get_stored_tx(&self, entry: &TxLogEntry) -> Result, ErrorKind> { - Owner::get_stored_tx(self, entry).map_err(|e| e.kind()) + fn get_stored_tx(&self, tx: &TxLogEntry) -> Result, ErrorKind> { + Owner::get_stored_tx(self, tx).map_err(|e| e.kind()) } fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), ErrorKind> { @@ -722,52 +1170,150 @@ where } } +/// helper to set up a real environment to run integrated doctests +pub fn run_doctest( + request: serde_json::Value, + test_dir: &str, + blocks_to_mine: u64, + perform_tx: bool, + lock_tx: bool, + finalize_tx: bool, +) -> Result, String> { + use crate::{Owner, OwnerRpc}; + use easy_jsonrpc::Handler; + use grin_keychain::ExtKeychain; + use grin_wallet_impls::test_framework::{self, LocalWalletClient, WalletProxy}; + + use crate::core::global; + use crate::core::global::ChainTypes; + use grin_util as util; + + use std::fs; + use std::thread; + + util::init_test_logger(); + let _ = fs::remove_dir_all(test_dir); + global::set_mining_mode(ChainTypes::AutomatedTesting); + + let mut wallet_proxy: WalletProxy = WalletProxy::new(test_dir); + let chain = wallet_proxy.chain.clone(); + + let rec_phrase_1 = + "fat twenty mean degree forget shell check candy immense awful \ + flame next during february bulb bike sun wink theory day kiwi embrace peace lunch"; + let client1 = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone()); + let wallet1 = test_framework::create_wallet( + &format!("{}/wallet1", test_dir), + client1.clone(), + Some(rec_phrase_1), + ); + wallet_proxy.add_wallet("wallet1", client1.get_send_instance(), wallet1.clone()); + + let rec_phrase_2 = + "hour kingdom ripple lunch razor inquiry coyote clay stamp mean \ + sell finish magic kid tiny wage stand panther inside settle feed song hole exile"; + let client2 = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone()); + let wallet2 = test_framework::create_wallet( + &format!("{}/wallet2", test_dir), + client2.clone(), + Some(rec_phrase_2), + ); + wallet_proxy.add_wallet("wallet2", client2.get_send_instance(), wallet2.clone()); + + // Set the wallet proxy listener running + thread::spawn(move || { + if let Err(e) = wallet_proxy.run() { + error!("Wallet Proxy error: {}", e); + } + }); + + // Mine a few blocks to wallet 1 so there's something to send + for _ in 0..blocks_to_mine { + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 1 as usize, false); + //update local outputs after each block, so transaction IDs stay consistent + let mut w = wallet1.lock(); + w.open_with_credentials().unwrap(); + let (wallet_refreshed, _) = + api_impl::owner::retrieve_summary_info(&mut *w, true, 1).unwrap(); + assert!(wallet_refreshed); + w.close().unwrap(); + } + + if perform_tx { + let amount = 60_000_000_000; + let mut w = wallet1.lock(); + w.open_with_credentials().unwrap(); + let mut slate = api_impl::owner::initiate_tx( + &mut *w, None, // account + amount, // amount + 2, // minimum confirmations + 500, // max outputs + 1, // num change outputs + true, // select all outputs + None, None, true, + ) + .unwrap(); + { + let mut w2 = wallet2.lock(); + w2.open_with_credentials().unwrap(); + api_impl::foreign::receive_tx(&mut *w2, &mut slate, None, None, true).unwrap(); + w2.close().unwrap(); + } + println!("RECIPIENT SLATE"); + // Spit out slate for input to finalize_tx + println!("{}", serde_json::to_string_pretty(&slate).unwrap()); + if lock_tx { + api_impl::owner::tx_lock_outputs(&mut *w, &slate).unwrap(); + } + if finalize_tx { + api_impl::owner::finalize_tx(&mut *w, &slate).unwrap(); + } + w.close().unwrap(); + } + + if perform_tx && lock_tx && finalize_tx { + // mine to move the chain on + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3 as usize, false); + } + + let mut api_owner = Owner::new(wallet1.clone()); + api_owner.doctest_mode = true; + let owner_api = &api_owner as &dyn OwnerRpc; + Ok(owner_api.handle_request(request)) +} + #[doc(hidden)] #[macro_export] macro_rules! doctest_helper_json_rpc_owner_assert_response { - ($request:tt, $expected_response:tt) => { + ($request:expr, $expected_response:expr, $blocks_to_mine:expr, $perform_tx:expr, $lock_tx:expr, $finalize_tx:expr) => { // create temporary wallet, run jsonrpc request on owner api of wallet, delete wallet, return // json response. // In order to prevent leaking tempdirs, This function should not panic. - fn rpc_owner_result( - request: serde_json::Value, - ) -> Result, String> { - use easy_jsonrpc::Handler; - use grin_keychain::ExtKeychain; - use grin_util::Mutex; - use grin_wallet_api::{Owner, OwnerRpc}; - use grin_wallet_config::WalletConfig; - use grin_wallet_impls::{HTTPNodeClient, LMDBBackend}; - use grin_wallet_libwallet::types::WalletBackend; - use serde_json; - use std::sync::Arc; - use tempfile::tempdir; + use grin_wallet_api::run_doctest; + use serde_json; + use serde_json::Value; + use tempfile::tempdir; - let dir = tempdir().map_err(|e| format!("{:#?}", e))?; - { - let mut wallet_config = WalletConfig::default(); - wallet_config.data_file_dir = dir - .path() - .to_str() - .ok_or("Failed to convert tmpdir path to string.".to_owned())? - .to_owned(); - let node_client = - HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); - let wallet: Arc>> = - Arc::new(Mutex::new( - LMDBBackend::new(wallet_config.clone(), "", node_client) - .map_err(|e| format!("{:#?}", e))?, - )); - let api_owner = Owner::new(wallet); - let owner_api = &api_owner as &dyn OwnerRpc; - Ok(owner_api.handle_request(request)) - } - } - - let response = rpc_owner_result(serde_json::json!($request)) - .unwrap() + let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap(); + let dir = dir + .path() + .to_str() + .ok_or("Failed to convert tmpdir path to string.".to_owned()) .unwrap(); - let expected_response = serde_json::json!($expected_response); + + let request_val: Value = serde_json::from_str($request).unwrap(); + let expected_response: Value = serde_json::from_str($expected_response).unwrap(); + + let response = run_doctest( + request_val, + dir, + $blocks_to_mine, + $perform_tx, + $lock_tx, + $finalize_tx, + ) + .unwrap() + .unwrap(); if response != expected_response { panic!( diff --git a/controller/Cargo.toml b/controller/Cargo.toml index 5f5d2109..fdb390cc 100644 --- a/controller/Cargo.toml +++ b/controller/Cargo.toml @@ -27,7 +27,7 @@ term = "0.5" tokio = "= 0.1.11" tokio-core = "0.1" tokio-retry = "0.1" -uuid = { version = "0.6", features = ["serde", "v4"] } +uuid = { version = "0.7", features = ["serde", "v4"] } url = "1.7.0" chrono = { version = "0.4.4", features = ["serde"] } diff --git a/controller/src/command.rs b/controller/src/command.rs index 3010a3fc..bb45f309 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -247,7 +247,7 @@ pub fn send( let strategies = vec!["smallest", "all"] .into_iter() .map(|strategy| { - let (total, fee) = api + let est = api .estimate_initiate_tx( None, args.amount, @@ -257,7 +257,7 @@ pub fn send( strategy == "all", ) .unwrap(); - (strategy, total, fee) + (strategy, est.total, est.fee) }) .collect(); display::estimate(args.amount, strategies, dark_scheme); @@ -307,7 +307,7 @@ pub fn send( error!("Error validating participant messages: {}", e); return Err(e); } - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; } else { adapter.send_tx_async(&args.dest, &slate)?; api.tx_lock_outputs(&slate)?; @@ -378,7 +378,7 @@ pub fn finalize( error!("Error validating participant messages: {}", e); return Err(e); } - let _ = api.finalize_tx(&mut slate).expect("Finalize failed"); + slate = api.finalize_tx(&mut slate).expect("Finalize failed"); let result = api.post_tx(&slate.tx, args.fluff); match result { diff --git a/controller/src/controller.rs b/controller/src/controller.rs index 4de4b7be..565564d4 100644 --- a/controller/src/controller.rs +++ b/controller/src/controller.rs @@ -23,10 +23,9 @@ use crate::impls::{FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCo use crate::keychain::Keychain; use crate::libwallet::slate::Slate; use crate::libwallet::types::{ - CbData, NodeClient, OutputData, SendTXArgs, TxLogEntry, WalletBackend, WalletInfo, + CbData, NodeClient, OutputCommitMapping, SendTXArgs, TxLogEntry, WalletBackend, WalletInfo, }; use crate::libwallet::{Error, ErrorKind}; -use crate::util::secp::pedersen; use crate::util::to_base64; use crate::util::Mutex; use failure::ResultExt; @@ -187,7 +186,7 @@ where &self, req: &Request, api: Owner, - ) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error> { + ) -> Result<(bool, Vec), Error> { let mut update_from_node = false; let mut id = None; let mut show_spent = false; @@ -373,7 +372,7 @@ where } api.tx_lock_outputs(&slate)?; if args.method != "file" { - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; } Ok(slate) })) @@ -385,8 +384,8 @@ where api: Owner, ) -> Box + Send> { Box::new( - parse_body(req).and_then(move |mut slate| match api.finalize_tx(&mut slate) { - Ok(_) => ok(slate.clone()), + parse_body(req).and_then(move |slate| match api.finalize_tx(&slate) { + Ok(s) => ok(s.clone()), Err(e) => { error!("finalize_tx: failed with error: {}", e); err(e) diff --git a/controller/src/display.rs b/controller/src/display.rs index 32a2395f..461d0ec4 100644 --- a/controller/src/display.rs +++ b/controller/src/display.rs @@ -14,10 +14,11 @@ use crate::core::core::{self, amount_to_hr_string}; use crate::core::global; -use crate::libwallet::types::{AcctPathMapping, OutputData, OutputStatus, TxLogEntry, WalletInfo}; +use crate::libwallet::types::{ + AcctPathMapping, OutputCommitMapping, OutputStatus, TxLogEntry, WalletInfo, +}; use crate::libwallet::Error; use crate::util; -use crate::util::secp::pedersen; use prettytable; use std::io::prelude::Write; use term; @@ -27,7 +28,7 @@ pub fn outputs( account: &str, cur_height: u64, validated: bool, - outputs: Vec<(OutputData, pedersen::Commitment)>, + outputs: Vec, dark_background_color_scheme: bool, ) -> Result<(), Error> { let title = format!( @@ -54,25 +55,25 @@ pub fn outputs( bMG->"Tx" ]); - for (out, commit) in outputs { - let commit = format!("{}", util::to_hex(commit.as_ref().to_vec())); - let index = match out.mmr_index { + for m in outputs { + let commit = format!("{}", util::to_hex(m.commit.as_ref().to_vec())); + let index = match m.output.mmr_index { None => "None".to_owned(), Some(t) => t.to_string(), }; - let height = format!("{}", out.height); - let lock_height = format!("{}", out.lock_height); - let is_coinbase = format!("{}", out.is_coinbase); + let height = format!("{}", m.output.height); + let lock_height = format!("{}", m.output.lock_height); + let is_coinbase = format!("{}", m.output.is_coinbase); // Mark unconfirmed coinbase outputs as "Mining" instead of "Unconfirmed" - let status = match out.status { - OutputStatus::Unconfirmed if out.is_coinbase => "Mining".to_string(), - _ => format!("{}", out.status), + let status = match m.output.status { + OutputStatus::Unconfirmed if m.output.is_coinbase => "Mining".to_string(), + _ => format!("{}", m.output.status), }; - let num_confirmations = format!("{}", out.num_confirmations(cur_height)); - let value = format!("{}", core::amount_to_hr_string(out.value, false)); - let tx = match out.tx_log_entry { + let num_confirmations = format!("{}", m.output.num_confirmations(cur_height)); + let value = format!("{}", core::amount_to_hr_string(m.output.value, false)); + let tx = match m.output.tx_log_entry { None => "".to_owned(), Some(t) => t.to_string(), }; diff --git a/controller/tests/accounts.rs b/controller/tests/accounts.rs index 09b8a6fe..7f613848 100644 --- a/controller/tests/accounts.rs +++ b/controller/tests/accounts.rs @@ -111,14 +111,14 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { w.set_parent_key_id_by_name("account1")?; assert_eq!(w.parent_key_id(), ExtKeychain::derive_key_id(2, 1, 0, 0, 0)); } - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 7); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 7, false); { let mut w = wallet1.lock(); w.set_parent_key_id_by_name("account2")?; assert_eq!(w.parent_key_id(), ExtKeychain::derive_key_id(2, 2, 0, 0, 0)); } - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false); // Should have 5 in account1 (5 spendable), 5 in account (2 spendable) wallet::controller::owner_single_use(wallet1.clone(), |api| { @@ -188,7 +188,7 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client1.send_tx_slate_direct("wallet2", &slate)?; api.tx_lock_outputs(&slate)?; - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; api.post_tx(&slate.tx, false)?; Ok(()) })?; diff --git a/controller/tests/check.rs b/controller/tests/check.rs index c879bae8..8cad79e1 100644 --- a/controller/tests/check.rs +++ b/controller/tests/check.rs @@ -38,7 +38,7 @@ macro_rules! send_to_dest { WalletInst, LocalWalletClient, ExtKeychain, - >($a, $b, $c, $d) + >($a, $b, $c, $d, false) }; } @@ -111,7 +111,7 @@ fn check_repair_impl(test_dir: &str) -> Result<(), libwallet::Error> { // Do some mining let bh = 20u64; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false); // Sanity check contents wallet::controller::owner_single_use(wallet1.clone(), |api| { @@ -135,7 +135,7 @@ fn check_repair_impl(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; let w1_outputs: Vec = - w1_outputs_commits.into_iter().map(|o| o.0).collect(); + w1_outputs_commits.into_iter().map(|m| m.output).collect(); { let mut w = wallet1.lock(); w.open_with_credentials()?; @@ -337,7 +337,7 @@ fn two_wallets_one_seed_impl(test_dir: &str) -> Result<(), libwallet::Error> { // Do some mining let mut bh = 20u64; let base_amount = consensus::GRIN_BASE; - let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), bh as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), bh as usize, false); // send some funds to wallets 1 send_to_dest!(miner.clone(), m_client.clone(), "wallet1", base_amount * 1)?; @@ -360,7 +360,7 @@ fn two_wallets_one_seed_impl(test_dir: &str) -> Result<(), libwallet::Error> { send_to_dest!(miner.clone(), m_client.clone(), "wallet2", base_amount * 6)?; bh += 3; - let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm); + let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false); bh += cm as u64; // confirm balances @@ -411,7 +411,7 @@ fn two_wallets_one_seed_impl(test_dir: &str) -> Result<(), libwallet::Error> { send_to_dest!(miner.clone(), m_client.clone(), "wallet4", base_amount * 9)?; bh += 3; - let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm); + let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false); bh += cm as u64; wallet::controller::owner_single_use(wallet4.clone(), |api| { @@ -442,7 +442,7 @@ fn two_wallets_one_seed_impl(test_dir: &str) -> Result<(), libwallet::Error> { send_to_dest!(miner.clone(), m_client.clone(), "wallet6", base_amount * 12)?; bh += 3; - let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm as usize, false); bh += cm as u64; wallet::controller::owner_single_use(wallet6.clone(), |api| { @@ -487,7 +487,7 @@ fn two_wallets_one_seed_impl(test_dir: &str) -> Result<(), libwallet::Error> { bh += 3; // check balances - let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm); + let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false); bh += cm as u64; wallet::controller::owner_single_use(wallet7.clone(), |api| { @@ -552,7 +552,7 @@ fn two_wallets_one_seed_impl(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm); + let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false); // 7) Ensure check_repair creates missing accounts wallet::controller::owner_single_use(wallet10.clone(), |api| { diff --git a/controller/tests/file.rs b/controller/tests/file.rs index f68809d2..06cc1abd 100644 --- a/controller/tests/file.rs +++ b/controller/tests/file.rs @@ -89,7 +89,7 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { w.set_parent_key_id_by_name("mining")?; } let mut bh = 10u64; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false); let send_file = format!("{}/part_tx_1.tx", test_dir); let receive_file = format!("{}/part_tx_2.tx", test_dir); @@ -153,13 +153,13 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { let adapter = FileWalletCommAdapter::new(); let mut slate = adapter.receive_tx_async(&receive_file)?; api.verify_slate_messages(&slate)?; - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; api.post_tx(&slate.tx, false)?; bh += 1; Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); bh += 3; // Check total in mining account diff --git a/controller/tests/repost.rs b/controller/tests/repost.rs index af84b770..6f1d96d0 100644 --- a/controller/tests/repost.rs +++ b/controller/tests/repost.rs @@ -88,7 +88,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { w.set_parent_key_id_by_name("mining")?; } let mut bh = 10u64; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false); let send_file = format!("{}/part_tx_1.tx", test_dir); let receive_file = format!("{}/part_tx_2.tx", test_dir); @@ -119,7 +119,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); bh += 3; // wallet 1 receives file to different account, completes @@ -146,7 +146,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { wallet::controller::owner_single_use(wallet1.clone(), |api| { let adapter = FileWalletCommAdapter::new(); slate = adapter.receive_tx_async(&receive_file)?; - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; Ok(()) })?; @@ -159,7 +159,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); bh += 3; // update/test contents of both accounts @@ -211,11 +211,11 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client1.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&mut slate)?; Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); bh += 3; // Now repost from cached @@ -227,7 +227,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); bh += 3; // // update/test contents of both accounts diff --git a/controller/tests/restore.rs b/controller/tests/restore.rs index 98f7d1ca..951c2177 100644 --- a/controller/tests/restore.rs +++ b/controller/tests/restore.rs @@ -228,7 +228,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { }); // mine a few blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10, false); // assert wallet contents // and a single use api for a send command @@ -246,13 +246,13 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client1.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; sender_api.post_tx(&slate.tx, false)?; Ok(()) })?; // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); // Send some to wallet 3 wallet::controller::owner_single_use(wallet1.clone(), |sender_api| { @@ -269,13 +269,13 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client1.send_tx_slate_direct("wallet3", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; sender_api.post_tx(&slate.tx, false)?; Ok(()) })?; // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet3.clone(), 10); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet3.clone(), 10, false); // Wallet3 to wallet 2 wallet::controller::owner_single_use(wallet3.clone(), |sender_api| { @@ -292,7 +292,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client3.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; sender_api.post_tx(&slate.tx, false)?; Ok(()) })?; @@ -304,7 +304,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { } // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 2); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 2, false); // Wallet3 to wallet 2 again (to another account) wallet::controller::owner_single_use(wallet3.clone(), |sender_api| { @@ -321,13 +321,13 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client3.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; sender_api.post_tx(&slate.tx, false)?; Ok(()) })?; // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false); // update everyone wallet::controller::owner_single_use(wallet1.clone(), |api| { diff --git a/controller/tests/self_send.rs b/controller/tests/self_send.rs index 1755160b..8543cb60 100644 --- a/controller/tests/self_send.rs +++ b/controller/tests/self_send.rs @@ -76,7 +76,7 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { w.set_parent_key_id_by_name("mining")?; } let mut bh = 10u64; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false); // Should have 5 in account1 (5 spendable), 5 in account (2 spendable) wallet::controller::owner_single_use(wallet1.clone(), |api| { @@ -101,13 +101,13 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { api.receive_tx(&mut slate, Some("listener"), None)?; Ok(()) })?; - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; api.post_tx(&slate.tx, false)?; // mines a block bh += 1; Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); bh += 3; // Check total in mining account diff --git a/controller/tests/transaction.rs b/controller/tests/transaction.rs index 2171404b..66c88029 100644 --- a/controller/tests/transaction.rs +++ b/controller/tests/transaction.rs @@ -75,7 +75,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { let reward = core::consensus::REWARD; let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height // mine a few blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10, false); // Check wallet 1 contents are as expected wallet::controller::owner_single_use(wallet1.clone(), |api| { @@ -114,7 +114,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { slate = client1.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; // Check we have a single kernel and that it is a Plain kernel (no lock_height). assert_eq!(slate.tx.kernels().len(), 1); @@ -213,7 +213,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { })?; // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); // refresh wallets and retrieve info/tests for each wallet after maturity wallet::controller::owner_single_use(wallet1.clone(), |api| { @@ -249,7 +249,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { // Estimate fee and locked amount for a transaction wallet::controller::owner_single_use(wallet1.clone(), |sender_api| { - let (total, fee) = sender_api.estimate_initiate_tx( + let est = sender_api.estimate_initiate_tx( None, amount * 2, // amount 2, // minimum confirmations @@ -257,10 +257,10 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { 1, // num change outputs true, // select all outputs )?; - assert_eq!(total, 600_000_000_000); - assert_eq!(fee, 4_000_000); + assert_eq!(est.total, 600_000_000_000); + assert_eq!(est.fee, 4_000_000); - let (total, fee) = sender_api.estimate_initiate_tx( + let est = sender_api.estimate_initiate_tx( None, amount * 2, // amount 2, // minimum confirmations @@ -268,8 +268,8 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { 1, // num change outputs false, // select the smallest amount of outputs )?; - assert_eq!(total, 180_000_000_000); - assert_eq!(fee, 6_000_000); + assert_eq!(est.total, 180_000_000_000); + assert_eq!(est.fee, 6_000_000); Ok(()) })?; @@ -290,7 +290,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client1.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; Ok(()) })?; @@ -315,7 +315,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { })?; // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false); // check wallet2 has stored transaction wallet::controller::owner_single_use(wallet2.clone(), |api| { @@ -371,7 +371,7 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> { let reward = core::consensus::REWARD; let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height // mine a few blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false); let amount = 30_000_000_000; let mut slate = Slate::blank(1); @@ -387,7 +387,7 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> { )?; slate = client1.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(&slate)?; - sender_api.finalize_tx(&mut slate)?; + slate = sender_api.finalize_tx(&slate)?; Ok(()) })?; @@ -406,16 +406,16 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> { let mut locked_count = 0; let mut unconfirmed_count = 0; // get the tx entry, check outputs are as expected - let (_, outputs) = api.retrieve_outputs(true, false, Some(tx.unwrap().id))?; - for (o, _) in outputs.clone() { - if o.status == OutputStatus::Locked { + let (_, output_mappings) = api.retrieve_outputs(true, false, Some(tx.unwrap().id))?; + for m in output_mappings.clone() { + if m.output.status == OutputStatus::Locked { locked_count = locked_count + 1; } - if o.status == OutputStatus::Unconfirmed { + if m.output.status == OutputStatus::Unconfirmed { unconfirmed_count = unconfirmed_count + 1; } } - assert_eq!(outputs.len(), 3); + assert_eq!(output_mappings.len(), 3); assert_eq!(locked_count, 2); assert_eq!(unconfirmed_count, 1); @@ -431,8 +431,8 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> { assert!(tx.is_some()); // get the tx entry, check outputs are as expected let (_, outputs) = api.retrieve_outputs(true, false, Some(tx.unwrap().id))?; - for (o, _) in outputs.clone() { - if o.status == OutputStatus::Unconfirmed { + for m in outputs.clone() { + if m.output.status == OutputStatus::Unconfirmed { unconfirmed_count = unconfirmed_count + 1; } } @@ -447,7 +447,7 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> { // wallet 1 is bold and doesn't ever post the transaction // mine a few more blocks - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false); // Wallet 1 decides to roll back instead wallet::controller::owner_single_use(wallet1.clone(), |api| { diff --git a/impls/Cargo.toml b/impls/Cargo.toml index d18282d6..f79b0789 100644 --- a/impls/Cargo.toml +++ b/impls/Cargo.toml @@ -24,7 +24,7 @@ ring = "0.13" tokio = "= 0.1.11" tokio-core = "0.1" tokio-retry = "0.1" -uuid = { version = "0.6", features = ["serde", "v4"] } +uuid = { version = "0.7", features = ["serde", "v4"] } chrono = { version = "0.4.4", features = ["serde"] } grin_wallet_libwallet = { path = "../libwallet", version = "1.1.0" } diff --git a/impls/src/adapters/keybase.rs b/impls/src/adapters/keybase.rs index 5cbeb711..4d7f03e3 100644 --- a/impls/src/adapters/keybase.rs +++ b/impls/src/adapters/keybase.rs @@ -382,7 +382,7 @@ impl WalletCommAdapter for KeybaseWalletCommAdapter { let res = { let mut w = wallet.lock(); w.open_with_credentials()?; - let r = foreign::receive_tx(&mut *w, &mut slate, None, None); + let r = foreign::receive_tx(&mut *w, &mut slate, None, None, false); w.close()?; r }; diff --git a/impls/src/test_framework/mod.rs b/impls/src/test_framework/mod.rs index 0c850e85..dd22343f 100644 --- a/impls/src/test_framework/mod.rs +++ b/impls/src/test_framework/mod.rs @@ -32,6 +32,7 @@ use grin_core as core; use grin_keychain as keychain; use grin_util as util; use std::sync::Arc; +use std::thread; mod testclient; @@ -140,6 +141,7 @@ pub fn award_blocks_to_wallet( chain: &Chain, wallet: Arc>>, number: usize, + pause_between: bool, ) -> Result<(), libwallet::Error> where C: NodeClient, @@ -147,6 +149,9 @@ where { for _ in 0..number { award_block_to_wallet(chain, vec![], wallet.clone())?; + if pause_between { + thread::sleep(std::time::Duration::from_millis(100)); + } } Ok(()) } @@ -185,6 +190,7 @@ pub fn send_to_dest( client: LocalWalletClient, dest: &str, amount: u64, + test_mode: bool, ) -> Result<(), libwallet::Error> where T: WalletBackend, @@ -201,11 +207,11 @@ where 500, // max outputs 1, // num change outputs true, // select all outputs - None, None, + None, None, test_mode, )?; - let mut slate = client.send_tx_slate_direct(dest, &slate_i)?; + let slate = client.send_tx_slate_direct(dest, &slate_i)?; owner::tx_lock_outputs(&mut *w, &slate)?; - owner::finalize_tx(&mut *w, &mut slate)?; + let slate = owner::finalize_tx(&mut *w, &slate)?; w.close()?; slate }; diff --git a/impls/src/test_framework/testclient.rs b/impls/src/test_framework/testclient.rs index f3576ef7..1e2be6ae 100644 --- a/impls/src/test_framework/testclient.rs +++ b/impls/src/test_framework/testclient.rs @@ -220,7 +220,7 @@ where let mut w = wallet.1.lock(); w.open_with_credentials()?; // receive tx - foreign::receive_tx(&mut *w, &mut slate, None, None)?; + foreign::receive_tx(&mut *w, &mut slate, None, None, false)?; w.close()?; } diff --git a/integration/tests/framework.rs b/integration/tests/framework.rs index 21bb52ba..32565c87 100644 --- a/integration/tests/framework.rs +++ b/integration/tests/framework.rs @@ -28,11 +28,11 @@ use grin_keychain as keychain; use grin_p2p as p2p; use grin_servers as servers; use grin_util as util; +use p2p::PeerAddr; use std::default::Default; use std::ops::Deref; use std::sync::Arc; use std::{fs, thread, time}; -use p2p::PeerAddr; /// Just removes all results from previous runs pub fn clean_all_output(test_name_dir: &str) { @@ -197,7 +197,9 @@ impl LocalServerContainer { if self.config.seed_addr.len() > 0 { seeding_type = p2p::Seeding::List; - seeds = vec![PeerAddr::from_ip(self.config.seed_addr.to_string().parse().unwrap())]; + seeds = vec![PeerAddr::from_ip( + self.config.seed_addr.to_string().parse().unwrap(), + )]; } let s = servers::Server::new(servers::ServerConfig { @@ -357,8 +359,7 @@ impl LocalServerContainer { .unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config)); wallet.keychain = Some(keychain); let parent_id = keychain::ExtKeychain::derive_key_id(2, 0, 0, 0, 0); - let _ = - libwallet::internal::updater::refresh_outputs(&mut wallet, &parent_id, false); + let _ = libwallet::internal::updater::refresh_outputs(&mut wallet, &parent_id, false); libwallet::internal::updater::retrieve_info(&mut wallet, &parent_id, 1).unwrap() } @@ -401,7 +402,7 @@ impl LocalServerContainer { None, )?; slate = client_w.send_tx_sync(dest, &slate)?; - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; api.tx_lock_outputs(&slate, lock_fn)?; println!( "Tx sent: {} grin to {} (strategy '{}')", @@ -655,7 +656,9 @@ pub fn config(n: u16, test_name_dir: &str, seed_n: u16) -> servers::ServerConfig p2p_config: p2p::P2PConfig { port: 10000 + n, seeding_type: p2p::Seeding::List, - seeds: Some(vec![PeerAddr::from_ip(format!("127.0.0.1:{}", 10000 + seed_n).parse().unwrap())]), + seeds: Some(vec![PeerAddr::from_ip( + format!("127.0.0.1:{}", 10000 + seed_n).parse().unwrap(), + )]), ..p2p::P2PConfig::default() }, chain_type: core::global::ChainTypes::AutomatedTesting, diff --git a/integration/tests/simulnet.rs b/integration/tests/simulnet.rs index b3ca5cdb..744b7d1d 100644 --- a/integration/tests/simulnet.rs +++ b/integration/tests/simulnet.rs @@ -35,12 +35,12 @@ use grin_keychain as keychain; use grin_p2p as p2p; use grin_servers as servers; use grin_util as util; +use p2p::PeerAddr; use std::cmp; use std::default::Default; use std::process::exit; use std::sync::Arc; use std::{thread, time}; -use p2p::PeerAddr; use crate::framework::{ config, stop_all_servers, LocalServerContainerConfig, LocalServerContainerPool, @@ -948,7 +948,8 @@ fn replicate_tx_fluff_failure() { for i in 0..dl_nodes { // (create some stem nodes) let mut s_config = framework::config(3002 + i, "tx_fluff", 3002 + i); - s_config.p2p_config.seeds = Some(vec![PeerAddr::from_ip("127.0.0.1:13000".parse().unwrap())]); + s_config.p2p_config.seeds = + Some(vec![PeerAddr::from_ip("127.0.0.1:13000".parse().unwrap())]); s_config.dandelion_config.embargo_secs = Some(10); s_config.dandelion_config.patience_secs = Some(1); s_config.dandelion_config.relay_secs = Some(1); @@ -973,7 +974,7 @@ fn replicate_tx_fluff_failure() { None, )?; slate = client1_w.send_tx_sync(dest, &slate)?; - api.finalize_tx(&mut slate)?; + slate = api.finalize_tx(&slate)?; api.tx_lock_outputs(&slate, lock_fn)?; api.post_tx(&slate.tx, false)?; Ok(()) diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index 997fab6b..bc7dd710 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -20,8 +20,9 @@ serde = "1" serde_derive = "1" serde_json = "1" log = "0.4" -uuid = { version = "0.6", features = ["serde", "v4"] } +uuid = { version = "0.7", features = ["serde", "v4"] } chrono = { version = "0.4.4", features = ["serde"] } +lazy_static = "1" grin_core = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" } grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" } diff --git a/libwallet/src/api_impl/foreign.rs b/libwallet/src/api_impl/foreign.rs index 1beed5c2..a4eeb924 100644 --- a/libwallet/src/api_impl/foreign.rs +++ b/libwallet/src/api_impl/foreign.rs @@ -43,6 +43,7 @@ pub fn receive_tx( slate: &mut Slate, dest_acct_name: Option<&str>, message: Option, + use_test_rng: bool, ) -> Result<(), Error> where T: WalletBackend, @@ -75,7 +76,7 @@ where None => None, }; - tx::add_output_to_slate(&mut *w, slate, &parent_key_id, 1, message)?; + tx::add_output_to_slate(&mut *w, slate, &parent_key_id, 1, message, use_test_rng)?; tx::update_message(&mut *w, slate)?; Ok(()) } diff --git a/libwallet/src/api_impl/owner.rs b/libwallet/src/api_impl/owner.rs index 07973687..9b591fb1 100644 --- a/libwallet/src/api_impl/owner.rs +++ b/libwallet/src/api_impl/owner.rs @@ -24,9 +24,9 @@ use crate::internal::{keys, selection, tx, updater}; use crate::keychain::{Identifier, Keychain}; use crate::slate::Slate; use crate::types::{ - AcctPathMapping, NodeClient, OutputData, TxLogEntry, TxWrapper, WalletBackend, WalletInfo, + AcctPathMapping, NodeClient, OutputCommitMapping, TxEstimation, TxLogEntry, TxWrapper, + WalletBackend, WalletInfo, }; -use crate::util::secp::pedersen; use crate::{Error, ErrorKind}; const USER_MESSAGE_MAX_LEN: usize = 256; @@ -67,7 +67,7 @@ pub fn retrieve_outputs( include_spent: bool, refresh_from_node: bool, tx_id: Option, -) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error> +) -> Result<(bool, Vec), Error> where T: WalletBackend, C: NodeClient, @@ -144,6 +144,7 @@ pub fn initiate_tx( selection_strategy_is_use_all: bool, message: Option, target_slate_version: Option, + use_test_rng: bool, ) -> Result where T: WalletBackend, @@ -169,7 +170,7 @@ where None => None, }; - let mut slate = tx::new_tx_slate(&mut *w, amount, 2)?; + let mut slate = tx::new_tx_slate(&mut *w, amount, 2, use_test_rng)?; let context = tx::add_inputs_to_slate( &mut *w, @@ -181,6 +182,7 @@ where &parent_key_id, 0, message, + use_test_rng, )?; // Save the aggsig context in our DB for when we @@ -205,13 +207,7 @@ pub fn estimate_initiate_tx( max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, -) -> Result< - ( - u64, // total - u64, // fee - ), - Error, -> +) -> Result where T: WalletBackend, C: NodeClient, @@ -227,7 +223,7 @@ where } None => w.parent_key_id(), }; - tx::estimate_send_tx( + let (total, fee) = tx::estimate_send_tx( &mut *w, amount, minimum_confirmations, @@ -235,7 +231,8 @@ where num_change_outputs, selection_strategy_is_use_all, &parent_key_id, - ) + )?; + Ok(TxEstimation { total, fee }) } /// Lock sender outputs @@ -250,22 +247,23 @@ where } /// Finalize slate -pub fn finalize_tx(w: &mut T, slate: &mut Slate) -> Result<(), Error> +pub fn finalize_tx(w: &mut T, slate: &Slate) -> Result where T: WalletBackend, C: NodeClient, K: Keychain, { - let context = w.get_private_context(slate.id.as_bytes())?; - tx::complete_tx(&mut *w, slate, 0, &context)?; - tx::update_stored_tx(&mut *w, slate)?; - tx::update_message(&mut *w, slate)?; + let mut sl = slate.clone(); + let context = w.get_private_context(sl.id.as_bytes())?; + tx::complete_tx(&mut *w, &mut sl, 0, &context)?; + tx::update_stored_tx(&mut *w, &mut sl)?; + tx::update_message(&mut *w, &mut sl)?; { let mut batch = w.batch()?; - batch.delete_private_context(slate.id.as_bytes())?; + batch.delete_private_context(sl.id.as_bytes())?; batch.commit()?; } - Ok(()) + Ok(sl) } /// cancel tx @@ -360,7 +358,7 @@ where Ok(height) => Ok((height, true)), Err(_) => { let outputs = retrieve_outputs(w, true, false, None)?; - let height = match outputs.1.iter().map(|(out, _)| out.height).max() { + let height = match outputs.1.iter().map(|m| m.output.height).max() { Some(height) => height, None => 0, }; diff --git a/libwallet/src/internal/restore.rs b/libwallet/src/internal/restore.rs index a07dde7f..c911c6f0 100644 --- a/libwallet/src/internal/restore.rs +++ b/libwallet/src/internal/restore.rs @@ -293,14 +293,14 @@ where // check all definitive outputs exist in the wallet outputs for deffo in chain_outs.into_iter() { - let matched_out = wallet_outputs.iter().find(|wo| wo.1 == deffo.commit); + let matched_out = wallet_outputs.iter().find(|wo| wo.commit == deffo.commit); match matched_out { Some(s) => { - if s.0.status == OutputStatus::Spent { - accidental_spend_outs.push((s.0.clone(), deffo.clone())); + if s.output.status == OutputStatus::Spent { + accidental_spend_outs.push((s.output.clone(), deffo.clone())); } - if s.0.status == OutputStatus::Locked { - locked_outs.push((s.0.clone(), deffo.clone())); + if s.output.status == OutputStatus::Locked { + locked_outs.push((s.output.clone(), deffo.clone())); } } None => missing_outs.push(deffo), @@ -351,17 +351,17 @@ where batch.commit()?; } - let unconfirmed_outs: Vec<&(OutputData, pedersen::Commitment)> = wallet_outputs + let unconfirmed_outs: Vec<&OutputCommitMapping> = wallet_outputs .iter() - .filter(|o| o.0.status == OutputStatus::Unconfirmed) + .filter(|o| o.output.status == OutputStatus::Unconfirmed) .collect(); // Delete unconfirmed outputs for m in unconfirmed_outs.into_iter() { - let o = m.0.clone(); + let o = m.output.clone(); warn!( "Unconfirmed output for {} with ID {} ({:?}) not in UTXO set. \ Deleting and cancelling associated transaction log entries.", - o.value, o.key_id, m.1, + o.value, o.key_id, m.commit, ); cancel_tx_log_entry(wallet, &o)?; let mut batch = wallet.batch()?; diff --git a/libwallet/src/internal/selection.rs b/libwallet/src/internal/selection.rs index 2e49dd20..2312958e 100644 --- a/libwallet/src/internal/selection.rs +++ b/libwallet/src/internal/selection.rs @@ -36,6 +36,7 @@ pub fn build_send_tx( change_outputs: usize, selection_strategy_is_use_all: bool, parent_key_id: Identifier, + use_test_nonce: bool, ) -> Result where T: WalletBackend, @@ -64,6 +65,7 @@ where wallet.keychain().secp(), blinding.secret_key(&keychain.secp()).unwrap(), &parent_key_id, + use_test_nonce, ); context.fee = fee; @@ -171,6 +173,7 @@ pub fn build_recipient_output( wallet: &mut T, slate: &mut Slate, parent_key_id: Identifier, + use_test_rng: bool, ) -> Result<(Identifier, Context), Error> where T: WalletBackend, @@ -196,6 +199,7 @@ where .secret_key(wallet.keychain().clone().secp()) .unwrap(), &parent_key_id, + use_test_rng, ); context.add_output(&key_id, &None, amount); diff --git a/libwallet/src/internal/tx.rs b/libwallet/src/internal/tx.rs index ae95a675..287841bd 100644 --- a/libwallet/src/internal/tx.rs +++ b/libwallet/src/internal/tx.rs @@ -21,6 +21,12 @@ use crate::keychain::{Identifier, Keychain}; use crate::slate::Slate; use crate::types::{Context, NodeClient, TxLogEntryType, WalletBackend}; use crate::{Error, ErrorKind}; +use util::Mutex; + +/// static for incrementing test UUIDs +lazy_static! { + static ref SLATE_COUNTER: Mutex = { Mutex::new(0) }; +} /// Creates a new slate for a transaction, can be called by anyone involved in /// the transaction (sender(s), receiver(s)) @@ -28,6 +34,7 @@ pub fn new_tx_slate( wallet: &mut T, amount: u64, num_participants: usize, + use_test_rng: bool, ) -> Result where T: WalletBackend, @@ -36,6 +43,14 @@ where { let current_height = wallet.w2n_client().get_chain_height()?; let mut slate = Slate::blank(num_participants); + if use_test_rng { + { + let sc = SLATE_COUNTER.lock(); + let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, *sc]; + slate.id = Uuid::from_slice(&bytes).unwrap(); + } + *SLATE_COUNTER.lock() += 1; + } slate.amount = amount; slate.height = current_height; @@ -103,6 +118,7 @@ pub fn add_inputs_to_slate( parent_key_id: &Identifier, participant_id: usize, message: Option, + use_test_rng: bool, ) -> Result where T: WalletBackend, @@ -127,6 +143,7 @@ where num_change_outputs, selection_strategy_is_use_all, parent_key_id.clone(), + use_test_rng, )?; // Generate a kernel offset and subtract from our context's secret key. Store @@ -138,6 +155,7 @@ where &context.sec_nonce, participant_id, message, + use_test_rng, )?; Ok(context) @@ -150,6 +168,7 @@ pub fn add_output_to_slate( parent_key_id: &Identifier, participant_id: usize, message: Option, + use_test_rng: bool, ) -> Result where T: WalletBackend, @@ -157,7 +176,8 @@ where K: Keychain, { // create an output using the amount in the slate - let (_, mut context) = selection::build_recipient_output(wallet, slate, parent_key_id.clone())?; + let (_, mut context) = + selection::build_recipient_output(wallet, slate, parent_key_id.clone(), use_test_rng)?; // fill public keys let _ = slate.fill_round_1( @@ -166,6 +186,7 @@ where &context.sec_nonce, 1, message, + false, )?; // perform partial sig @@ -233,7 +254,7 @@ where } // get outputs associated with tx let res = updater::retrieve_outputs(wallet, false, Some(tx.id), Some(&parent_key_id))?; - let outputs = res.iter().map(|(out, _)| out).cloned().collect(); + let outputs = res.iter().map(|m| m.output.clone()).collect(); updater::cancel_tx_and_outputs(wallet, tx, outputs, parent_key_id)?; Ok(()) } diff --git a/libwallet/src/internal/updater.rs b/libwallet/src/internal/updater.rs index f3176700..8150b28b 100644 --- a/libwallet/src/internal/updater.rs +++ b/libwallet/src/internal/updater.rs @@ -27,8 +27,8 @@ use crate::error::{Error, ErrorKind}; use crate::internal::keys; use crate::keychain::{Identifier, Keychain}; use crate::types::{ - BlockFees, CbData, NodeClient, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, - WalletBackend, WalletInfo, + BlockFees, CbData, NodeClient, OutputCommitMapping, OutputData, OutputStatus, TxLogEntry, + TxLogEntryType, WalletBackend, WalletInfo, }; use crate::util; use crate::util::secp::pedersen; @@ -39,7 +39,7 @@ pub fn retrieve_outputs( show_spent: bool, tx_id: Option, parent_key_id: Option<&Identifier>, -) -> Result, Error> +) -> Result, Error> where T: WalletBackend, C: NodeClient, @@ -72,12 +72,12 @@ where let res = outputs .into_iter() - .map(|out| { - let commit = match out.commit.clone() { + .map(|output| { + let commit = match output.commit.clone() { Some(c) => pedersen::Commitment::from_vec(util::from_hex(c).unwrap()), - None => keychain.commit(out.value, &out.key_id).unwrap(), + None => keychain.commit(output.value, &output.key_id).unwrap(), }; - (out, commit) + OutputCommitMapping { output, commit } }) .collect(); Ok(res) diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index 27ba3a5f..72b7c956 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -37,6 +37,8 @@ extern crate failure_derive; extern crate serde_derive; #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; pub mod api_impl; mod error; diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index b3e9320b..17284319 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -28,6 +28,7 @@ use grin_core::core::committed::Committed; use grin_core::core::transaction::{kernel_features, kernel_sig_msg, Transaction, Weighting}; use grin_core::core::verifier_cache::LruVerifierCache; use grin_core::libtx::{aggsig, build, secp_ser, tx_fee}; +use rand::rngs::mock::StepRng; use rand::thread_rng; use serde_json; use std::sync::Arc; @@ -44,6 +45,7 @@ const CURRENT_SLATE_VERSION: u16 = 2; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ParticipantData { /// Id of participant in the transaction. (For now, 0=sender, 1=rec) + #[serde(with = "secp_ser::string_or_u64")] pub id: u64, /// Public key corresponding to private blinding factor #[serde(with = "secp_ser::pubkey_serde")] @@ -82,6 +84,7 @@ impl ParticipantData { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ParticipantMessageData { /// id of the particpant in the tx + #[serde(with = "secp_ser::string_or_u64")] pub id: u64, /// Public key #[serde(with = "secp_ser::pubkey_serde")] @@ -122,12 +125,16 @@ pub struct Slate { /// inputs, outputs, kernels, kernel offset pub tx: Transaction, /// base amount (excluding fee) + #[serde(with = "secp_ser::string_or_u64")] pub amount: u64, /// fee amount + #[serde(with = "secp_ser::string_or_u64")] pub fee: u64, /// Block height for the transaction + #[serde(with = "secp_ser::string_or_u64")] pub height: u64, /// Lock height + #[serde(with = "secp_ser::string_or_u64")] pub lock_height: u64, /// Participant data, each participant in the transaction will /// insert their public data here. For now, 0 is sender and 1 @@ -268,13 +275,14 @@ impl Slate { sec_nonce: &SecretKey, participant_id: usize, message: Option, + use_test_rng: bool, ) -> Result<(), Error> where K: Keychain, { // Whoever does this first generates the offset if self.tx.offset == BlindingFactor::zero() { - self.generate_offset(keychain, sec_key)?; + self.generate_offset(keychain, sec_key, use_test_rng)?; } self.add_participant_info( keychain, @@ -283,6 +291,7 @@ impl Slate { participant_id, None, message, + use_test_rng, )?; Ok(()) } @@ -379,6 +388,7 @@ impl Slate { id: usize, part_sig: Option, message: Option, + use_test_rng: bool, ) -> Result<(), Error> where K: Keychain, @@ -386,12 +396,25 @@ impl Slate { // Add our public key and nonce to the slate let pub_key = PublicKey::from_secret_key(keychain.secp(), &sec_key)?; let pub_nonce = PublicKey::from_secret_key(keychain.secp(), &sec_nonce)?; + + let test_message_nonce = SecretKey::from_slice(&keychain.secp(), &[1; 32]).unwrap(); + let message_nonce = match use_test_rng { + false => None, + true => Some(&test_message_nonce), + }; + // Sign the provided message let message_sig = { if let Some(m) = message.clone() { let hashed = blake2b(secp::constants::MESSAGE_SIZE, &[], &m.as_bytes()[..]); let m = secp::Message::from_slice(&hashed.as_bytes())?; - let res = aggsig::sign_single(&keychain.secp(), &m, &sec_key, Some(&pub_key))?; + let res = aggsig::sign_single( + &keychain.secp(), + &m, + &sec_key, + message_nonce, + Some(&pub_key), + )?; Some(res) } else { None @@ -422,15 +445,29 @@ impl Slate { /// For now, we'll have the transaction initiator be responsible for it /// Return offset private key for the participant to use later in the /// transaction - fn generate_offset(&mut self, keychain: &K, sec_key: &mut SecretKey) -> Result<(), Error> + fn generate_offset( + &mut self, + keychain: &K, + sec_key: &mut SecretKey, + use_test_rng: bool, + ) -> Result<(), Error> where K: Keychain, { // Generate a random kernel offset here // and subtract it from the blind_sum so we create // the aggsig context with the "split" key - self.tx.offset = - BlindingFactor::from_secret_key(SecretKey::new(&keychain.secp(), &mut thread_rng())); + self.tx.offset = match use_test_rng { + false => { + BlindingFactor::from_secret_key(SecretKey::new(&keychain.secp(), &mut thread_rng())) + } + true => { + // allow for consistent test results + let mut test_rng = StepRng::new(1234567890u64, 1); + BlindingFactor::from_secret_key(SecretKey::new(&keychain.secp(), &mut test_rng)) + } + }; + let blind_offset = keychain.blind_sum( &BlindSum::new() .add_blinding_factor(BlindingFactor::from_secret_key(sec_key.clone())) diff --git a/libwallet/src/slate_versions/v2.rs b/libwallet/src/slate_versions/v2.rs index 1425378a..f762baed 100644 --- a/libwallet/src/slate_versions/v2.rs +++ b/libwallet/src/slate_versions/v2.rs @@ -61,12 +61,16 @@ pub struct SlateV2 { /// inputs, outputs, kernels, kernel offset pub tx: TransactionV2, /// base amount (excluding fee) + #[serde(with = "secp_ser::string_or_u64")] pub amount: u64, /// fee amount + #[serde(with = "secp_ser::string_or_u64")] pub fee: u64, /// Block height for the transaction + #[serde(with = "secp_ser::string_or_u64")] pub height: u64, /// Lock height + #[serde(with = "secp_ser::string_or_u64")] pub lock_height: u64, /// Participant data, each participant in the transaction will /// insert their public data here. For now, 0 is sender and 1 @@ -87,6 +91,7 @@ pub struct VersionCompatInfoV2 { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ParticipantDataV2 { /// Id of participant in the transaction. (For now, 0=sender, 1=rec) + #[serde(with = "secp_ser::string_or_u64")] pub id: u64, /// Public key corresponding to private blinding factor #[serde(with = "secp_ser::pubkey_serde")] @@ -164,9 +169,11 @@ pub struct TxKernelV2 { /// Options for a kernel's structure or use pub features: KernelFeatures, /// Fee originally included in the transaction this proof is for. + #[serde(with = "secp_ser::string_or_u64")] pub fee: u64, /// This kernel is not valid earlier than lock_height blocks /// The max lock_height of all *inputs* to this transaction + #[serde(with = "secp_ser::string_or_u64")] pub lock_height: u64, /// Remainder of the sum of all transaction commitments. If the transaction /// is well formed, amounts components should sum to zero and the excess diff --git a/libwallet/src/types.rs b/libwallet/src/types.rs index 87d5fbfa..608ea53d 100644 --- a/libwallet/src/types.rs +++ b/libwallet/src/types.rs @@ -17,7 +17,7 @@ use crate::core::core::hash::Hash; use crate::core::core::Transaction; -use crate::core::libtx::aggsig; +use crate::core::libtx::{aggsig, secp_ser}; use crate::core::ser; use crate::error::{Error, ErrorKind}; use crate::keychain::{Identifier, Keychain}; @@ -253,14 +253,18 @@ pub struct OutputData { pub commit: Option, /// PMMR Index, used on restore in case of duplicate wallets using the same /// key_id (2 wallets using same seed, for instance + #[serde(with = "secp_ser::opt_string_or_u64")] pub mmr_index: Option, /// Value of the output, necessary to rebuild the commitment + #[serde(with = "secp_ser::string_or_u64")] pub value: u64, /// Current status of the output pub status: OutputStatus, /// Height of the output + #[serde(with = "secp_ser::string_or_u64")] pub height: u64, /// Height we are locked until + #[serde(with = "secp_ser::string_or_u64")] pub lock_height: u64, /// Is this a coinbase output? Is it subject to coinbase locktime? pub is_coinbase: bool, @@ -369,6 +373,29 @@ impl fmt::Display for OutputStatus { } } +/// Map Outputdata to commits +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct OutputCommitMapping { + /// Output Data + pub output: OutputData, + /// The commit + #[serde( + serialize_with = "secp_ser::as_hex", + deserialize_with = "secp_ser::commitment_from_hex" + )] + pub commit: pedersen::Commitment, +} + +/// Transaction Estimate +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct TxEstimation { + /// Total amount to be locked + #[serde(with = "secp_ser::string_or_u64")] + pub total: u64, + /// Transaction Fee + #[serde(with = "secp_ser::string_or_u64")] + pub fee: u64, +} #[derive(Serialize, Deserialize, Clone, Debug)] /// Holds the context for a single aggsig transaction pub struct Context { @@ -391,11 +418,20 @@ pub struct Context { impl Context { /// Create a new context with defaults - pub fn new(secp: &secp::Secp256k1, sec_key: SecretKey, parent_key_id: &Identifier) -> Context { + pub fn new( + secp: &secp::Secp256k1, + sec_key: SecretKey, + parent_key_id: &Identifier, + use_test_rng: bool, + ) -> Context { + let sec_nonce = match use_test_rng { + false => aggsig::create_secnonce(secp).unwrap(), + true => SecretKey::from_slice(secp, &[1; 32]).unwrap(), + }; Context { parent_key_id: parent_key_id.clone(), sec_key: sec_key, - sec_nonce: aggsig::create_secnonce(secp).unwrap(), + sec_nonce, input_ids: vec![], output_ids: vec![], fee: 0, @@ -543,20 +579,28 @@ pub struct CbData { #[derive(Serialize, Eq, PartialEq, Deserialize, Debug, Clone)] pub struct WalletInfo { /// height from which info was taken + #[serde(with = "secp_ser::string_or_u64")] pub last_confirmed_height: u64, /// Minimum number of confirmations for an output to be treated as "spendable". + #[serde(with = "secp_ser::string_or_u64")] pub minimum_confirmations: u64, /// total amount in the wallet + #[serde(with = "secp_ser::string_or_u64")] pub total: u64, /// amount awaiting finalization + #[serde(with = "secp_ser::string_or_u64")] pub amount_awaiting_finalization: u64, /// amount awaiting confirmation + #[serde(with = "secp_ser::string_or_u64")] pub amount_awaiting_confirmation: u64, /// coinbases waiting for lock height + #[serde(with = "secp_ser::string_or_u64")] pub amount_immature: u64, /// amount currently spendable + #[serde(with = "secp_ser::string_or_u64")] pub amount_currently_spendable: u64, /// amount locked via previous transactions + #[serde(with = "secp_ser::string_or_u64")] pub amount_locked: u64, } @@ -615,10 +659,13 @@ pub struct TxLogEntry { /// number of outputs involved in TX pub num_outputs: usize, /// Amount credited via this transaction + #[serde(with = "secp_ser::string_or_u64")] pub amount_credited: u64, /// Amount debited via this transaction + #[serde(with = "secp_ser::string_or_u64")] pub amount_debited: u64, /// Fee + #[serde(with = "secp_ser::opt_string_or_u64")] pub fee: Option, /// Message data, stored as json pub messages: Option, diff --git a/libwallet/tests/libwallet.rs b/libwallet/tests/libwallet.rs index 6ded2667..1dcd5453 100644 --- a/libwallet/tests/libwallet.rs +++ b/libwallet/tests/libwallet.rs @@ -72,7 +72,7 @@ fn aggsig_sender_receiver_interaction() { let blind = blinding_factor.secret_key(&keychain.secp()).unwrap(); - s_cx = Context::new(&keychain.secp(), blind, &parent); + s_cx = Context::new(&keychain.secp(), blind, &parent, false); s_cx.get_public_keys(&keychain.secp()) }; @@ -86,7 +86,7 @@ fn aggsig_sender_receiver_interaction() { // let blind = blind_sum.secret_key(&keychain.secp())?; let blind = keychain.derive_key(0, &key_id).unwrap(); - rx_cx = Context::new(&keychain.secp(), blind, &parent); + rx_cx = Context::new(&keychain.secp(), blind, &parent, false); let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp()); rx_cx.add_output(&key_id, &None, 0); @@ -290,7 +290,7 @@ fn aggsig_sender_receiver_interaction_offset() { let blind = blinding_factor.secret_key(&keychain.secp()).unwrap(); - s_cx = Context::new(&keychain.secp(), blind, &parent); + s_cx = Context::new(&keychain.secp(), blind, &parent, false); s_cx.get_public_keys(&keychain.secp()) }; @@ -303,7 +303,7 @@ fn aggsig_sender_receiver_interaction_offset() { let blind = keychain.derive_key(0, &key_id).unwrap(); - rx_cx = Context::new(&keychain.secp(), blind, &parent); + rx_cx = Context::new(&keychain.secp(), blind, &parent, false); let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp()); rx_cx.add_output(&key_id, &None, 0); diff --git a/libwallet/tests/slates/v2.slate b/libwallet/tests/slates/v2.slate index 3258cbdb..84009170 100644 --- a/libwallet/tests/slates/v2.slate +++ b/libwallet/tests/slates/v2.slate @@ -29,21 +29,21 @@ "kernels": [ { "features": "HeightLocked", - "fee": 7000000, - "lock_height": 70194, + "fee": "7000000", + "lock_height": "70194", "excess": "000000000000000000000000000000000000000000000000000000000000000000", "excess_sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" } ] } }, - "amount": 84825921007, - "fee": 7000000, - "height": 70194, - "lock_height": 70194, + "amount": "84825921007", + "fee": "7000000", + "height": "70194", + "lock_height": "70194", "participant_data": [ { - "id": 0, + "id": "0", "public_blind_excess": "0391f8fc74bb5ff4de373352e7dee00860d4fb78ed7a99765585af980d8a31c615", "public_nonce": "0206562c21a7f3a003622722ee93c4ecbbecead4a6ad8ee5d930b51ca4a6ca6d01", "part_sig": null, diff --git a/src/bin/cmd/wallet_tests.rs b/src/bin/cmd/wallet_tests.rs index 8e7d36ed..57975938 100644 --- a/src/bin/cmd/wallet_tests.rs +++ b/src/bin/cmd/wallet_tests.rs @@ -245,7 +245,7 @@ mod wallet_tests { })?; let mut bh = 10u64; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false); let very_long_message = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef\ ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef\ @@ -320,7 +320,7 @@ mod wallet_tests { Ok(()) })?; - let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10); + let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10, false); bh += 10; // update info for each