mirror of
https://github.com/mimblewimble/grin-wallet.git
synced 2025-02-01 08:51:09 +03:00
parent
64772e6021
commit
94960b3edd
37 changed files with 1645 additions and 725 deletions
108
Cargo.lock
generated
108
Cargo.lock
generated
|
@ -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)" = "<none>"
|
||||
"checksum grin_util 1.1.0 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
|
||||
"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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
683
api/src/owner.rs
683
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<W: ?Sized, C, K>
|
||||
|
@ -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<Mutex<W>>,
|
||||
/// Flag to normalize some output during testing. Can mostly be ignored.
|
||||
pub doctest_mode: bool,
|
||||
phantom: PhantomData<K>,
|
||||
phantom_c: PhantomData<C>,
|
||||
}
|
||||
|
@ -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<Mutex<W>>) -> 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<OutputData, Commitment>`) - A tuple:
|
||||
/// * `(bool, Vec<OutputCommitMapping>)` - 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<u32>,
|
||||
) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error> {
|
||||
) -> Result<(bool, Vec<OutputCommitMapping>), 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<TxLogEntry)` - 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 set of retrieved
|
||||
/// [TxLogEntries](../types/struct/TxLogEntry.html)
|
||||
/// [TxLogEntries](../grin_wallet_libwallet/types/struct.TxLogEntry.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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<TxLogEntry>), 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||
/// # 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<TxEstimation, Error> {
|
||||
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<Slate, Error> {
|
||||
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<u32>, tx_slate_id: Option<Uuid>) -> 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<Option<Transaction>, 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<u32>, tx_slate_id: Option<Uuid>) -> 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<Option<Transaction>, 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<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> = Arc::new(
|
||||
Mutex::new(LMDBBackend::new(wallet_config.clone(), pw, node_client).unwrap()),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
1008
api/src/owner_rpc.rs
1008
api/src/owner_rpc.rs
File diff suppressed because it is too large
Load diff
|
@ -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"] }
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Body>,
|
||||
api: Owner<T, C, K>,
|
||||
) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error> {
|
||||
) -> Result<(bool, Vec<OutputCommitMapping>), 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<T, C, K>,
|
||||
) -> Box<dyn Future<Item = Slate, Error = Error> + 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)
|
||||
|
|
|
@ -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<OutputCommitMapping>,
|
||||
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(),
|
||||
};
|
||||
|
|
|
@ -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(())
|
||||
})?;
|
||||
|
|
|
@ -38,7 +38,7 @@ macro_rules! send_to_dest {
|
|||
WalletInst<LocalWalletClient, ExtKeychain>,
|
||||
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<libwallet::types::OutputData> =
|
||||
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| {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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<C, K>(
|
|||
chain: &Chain,
|
||||
wallet: Arc<Mutex<dyn WalletInst<C, K>>>,
|
||||
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<T: ?Sized, C, K>(
|
|||
client: LocalWalletClient,
|
||||
dest: &str,
|
||||
amount: u64,
|
||||
test_mode: bool,
|
||||
) -> Result<(), libwallet::Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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()?;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -43,6 +43,7 @@ pub fn receive_tx<T: ?Sized, C, K>(
|
|||
slate: &mut Slate,
|
||||
dest_acct_name: Option<&str>,
|
||||
message: Option<String>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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<T: ?Sized, C, K>(
|
|||
include_spent: bool,
|
||||
refresh_from_node: bool,
|
||||
tx_id: Option<u32>,
|
||||
) -> Result<(bool, Vec<(OutputData, pedersen::Commitment)>), Error>
|
||||
) -> Result<(bool, Vec<OutputCommitMapping>), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: NodeClient,
|
||||
|
@ -144,6 +144,7 @@ pub fn initiate_tx<T: ?Sized, C, K>(
|
|||
selection_strategy_is_use_all: bool,
|
||||
message: Option<String>,
|
||||
target_slate_version: Option<u16>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<Slate, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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<T: ?Sized, C, K>(
|
|||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<
|
||||
(
|
||||
u64, // total
|
||||
u64, // fee
|
||||
),
|
||||
Error,
|
||||
>
|
||||
) -> Result<TxEstimation, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
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<T: ?Sized, C, K>(w: &mut T, slate: &mut Slate) -> Result<(), Error>
|
||||
pub fn finalize_tx<T: ?Sized, C, K>(w: &mut T, slate: &Slate) -> Result<Slate, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
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,
|
||||
};
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -36,6 +36,7 @@ pub fn build_send_tx<T: ?Sized, C, K>(
|
|||
change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
parent_key_id: Identifier,
|
||||
use_test_nonce: bool,
|
||||
) -> Result<Context, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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<T: ?Sized, C, K>(
|
|||
wallet: &mut T,
|
||||
slate: &mut Slate,
|
||||
parent_key_id: Identifier,
|
||||
use_test_rng: bool,
|
||||
) -> Result<(Identifier, Context), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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);
|
||||
|
|
|
@ -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<u8> = { 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<T: ?Sized, C, K>(
|
|||
wallet: &mut T,
|
||||
amount: u64,
|
||||
num_participants: usize,
|
||||
use_test_rng: bool,
|
||||
) -> Result<Slate, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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<T: ?Sized, C, K>(
|
|||
parent_key_id: &Identifier,
|
||||
participant_id: usize,
|
||||
message: Option<String>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<Context, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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<T: ?Sized, C, K>(
|
|||
parent_key_id: &Identifier,
|
||||
participant_id: usize,
|
||||
message: Option<String>,
|
||||
use_test_rng: bool,
|
||||
) -> Result<Context, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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<T: ?Sized, C, K>(
|
|||
show_spent: bool,
|
||||
tx_id: Option<u32>,
|
||||
parent_key_id: Option<&Identifier>,
|
||||
) -> Result<Vec<(OutputData, pedersen::Commitment)>, Error>
|
||||
) -> Result<Vec<OutputCommitMapping>, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<String>,
|
||||
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<Signature>,
|
||||
message: Option<String>,
|
||||
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<K>(&mut self, keychain: &K, sec_key: &mut SecretKey) -> Result<(), Error>
|
||||
fn generate_offset<K>(
|
||||
&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()))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<String>,
|
||||
/// 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<u64>,
|
||||
/// 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<u64>,
|
||||
/// Message data, stored as json
|
||||
pub messages: Option<ParticipantMessages>,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue