mirror of
https://github.com/mimblewimble/grin-wallet.git
synced 2025-02-01 08:51:09 +03:00
move integration tests into wallet
This commit is contained in:
parent
84db57856e
commit
b6b3318b0d
10 changed files with 2731 additions and 10 deletions
|
@ -40,6 +40,8 @@ env:
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: TEST_SUITE=integration
|
||||
- os: linux
|
||||
env: TEST_SUITE=config-libwallet-apiwallet
|
||||
- os: linux
|
||||
|
|
173
Cargo.lock
generated
173
Cargo.lock
generated
|
@ -153,6 +153,11 @@ dependencies = [
|
|||
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bufstream"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.1"
|
||||
|
@ -414,6 +419,11 @@ name = "dtoa"
|
|||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.5"
|
||||
|
@ -546,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
[[package]]
|
||||
name = "grin_api"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
|
@ -596,7 +606,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "grin_chain"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
|
@ -618,7 +628,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "grin_core"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
|
@ -641,10 +651,42 @@ dependencies = [
|
|||
"uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_integration"
|
||||
version = "1.1.0"
|
||||
dependencies = [
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"grin_api 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_apiwallet 1.1.0",
|
||||
"grin_chain 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_core 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_keychain 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_libwallet 1.1.0",
|
||||
"grin_p2p 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_refwallet 1.1.0",
|
||||
"grin_servers 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_store 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_util 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_wallet_config 1.1.0",
|
||||
"http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lmdb-zero 0.4.4 (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.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_keychain"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
|
@ -687,7 +729,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "grin_p2p"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -708,7 +750,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "grin_pool"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
|
@ -770,10 +812,41 @@ dependencies = [
|
|||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_servers"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
dependencies = [
|
||||
"bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"grin_api 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_chain 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_core 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_keychain 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_p2p 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_pool 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_store 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_util 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_wallet 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper-staticfile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lmdb-zero 0.4.4 (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.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_store"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
|
@ -793,7 +866,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "grin_util"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#ee4eed71ea7e379f5c7e2ca08179c516c2d4be45"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
dependencies = [
|
||||
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -811,6 +884,39 @@ dependencies = [
|
|||
"zip 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_wallet"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0#cbac14c1353ae011ea9452196fcb26fd64e65141"
|
||||
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)",
|
||||
"chrono 0.4.6 (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)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"grin_api 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_chain 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_core 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_keychain 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_store 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"grin_util 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)",
|
||||
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"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)",
|
||||
"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)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grin_wallet"
|
||||
version = "1.1.0"
|
||||
|
@ -943,6 +1049,19 @@ dependencies = [
|
|||
"webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-staticfile"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.1.5"
|
||||
|
@ -967,11 +1086,31 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "jsonrpc-core"
|
||||
version = "8.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
|
@ -1076,6 +1215,14 @@ dependencies = [
|
|||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.6"
|
||||
|
@ -1335,7 +1482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -2605,6 +2752,7 @@ dependencies = [
|
|||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
|
||||
"checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
|
||||
"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||
"checksum built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61f5aae2fa15b68fbcf0cbab64e659a55d10e9bacc55d3470ef77ae73030d755"
|
||||
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
|
||||
|
@ -2636,6 +2784,7 @@ dependencies = [
|
|||
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
|
||||
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
|
||||
"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
|
||||
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||
"checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd"
|
||||
"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
|
||||
"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
|
||||
|
@ -2660,8 +2809,10 @@ dependencies = [
|
|||
"checksum grin_p2p 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
|
||||
"checksum grin_pool 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
|
||||
"checksum grin_secp256k1zkp 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "223095ed6108a42855ab2ce368d2056cfd384705f81c494f6d88ab3383161562"
|
||||
"checksum grin_servers 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
|
||||
"checksum grin_store 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
|
||||
"checksum grin_util 1.0.1 (git+https://github.com/mimblewimble/grin?branch=milestone/1.1.0)" = "<none>"
|
||||
"checksum grin_wallet 1.0.1 (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 hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a"
|
||||
"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5"
|
||||
|
@ -2669,10 +2820,13 @@ dependencies = [
|
|||
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
||||
"checksum hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f1ebec079129e43af5e234ef36ee3d7e6085687d145b7ea653b262d16c6b65f1"
|
||||
"checksum hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68f2aa6b1681795bf4da8063f718cd23145aa0c9a5143d9787b345aa60d38ee4"
|
||||
"checksum hyper-staticfile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4080cb44b9c1e4c6dfd6f7ee85a9c3439777ec9c59df32f944836d3de58ac35e"
|
||||
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
|
||||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
||||
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||
|
@ -2686,6 +2840,7 @@ dependencies = [
|
|||
"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
|
||||
"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.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"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"
|
||||
|
|
|
@ -16,7 +16,7 @@ name = "grin-wallet"
|
|||
path = "src/bin/grin-wallet.rs"
|
||||
|
||||
[workspace]
|
||||
members = ["apiwallet", "config", "libwallet", "refwallet"]
|
||||
members = ["apiwallet", "config", "integration", "libwallet", "refwallet"]
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "2.31", features = ["yaml"] }
|
||||
|
|
40
integration/Cargo.toml
Normal file
40
integration/Cargo.toml
Normal file
|
@ -0,0 +1,40 @@
|
|||
[package]
|
||||
name = "grin_integration"
|
||||
version = "1.1.0"
|
||||
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
|
||||
description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format."
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/mimblewimble/grin"
|
||||
keywords = [ "crypto", "grin", "mimblewimble" ]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
hyper = "0.12"
|
||||
futures = "0.1"
|
||||
http = "0.1"
|
||||
itertools = "0.7"
|
||||
lmdb-zero = "0.4.4"
|
||||
rand = "0.5"
|
||||
serde = "1"
|
||||
log = "0.4"
|
||||
serde_derive = "1"
|
||||
serde_json = "1"
|
||||
chrono = "0.4.4"
|
||||
tokio = "0.1.11"
|
||||
blake2-rfc = "0.2"
|
||||
bufstream = "0.1"
|
||||
|
||||
grin_apiwallet = { path = "../apiwallet", version = "1.1.0" }
|
||||
grin_libwallet = { path = "../libwallet", version = "1.1.0" }
|
||||
grin_refwallet = { path = "../refwallet", version = "1.1.0" }
|
||||
grin_wallet_config = { path = "../config", 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" }
|
||||
grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
|
||||
grin_util = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
|
||||
grin_api = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
|
||||
grin_store = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
|
||||
grin_p2p = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
|
||||
grin_servers = { git = "https://github.com/mimblewimble/grin", branch = "milestone/1.1.0" }
|
21
integration/src/lib.rs
Normal file
21
integration/src/lib.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2019 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Grin integration test crate
|
||||
|
||||
#![deny(non_upper_case_globals)]
|
||||
#![deny(non_camel_case_types)]
|
||||
#![deny(non_snake_case)]
|
||||
#![deny(unused_mut)]
|
||||
#![warn(missing_docs)]
|
485
integration/tests/api.rs
Normal file
485
integration/tests/api.rs
Normal file
|
@ -0,0 +1,485 @@
|
|||
// Copyright 2018 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod framework;
|
||||
|
||||
use self::core::global::{self, ChainTypes};
|
||||
use self::util::init_test_logger;
|
||||
use self::util::Mutex;
|
||||
use crate::framework::{LocalServerContainer, LocalServerContainerConfig};
|
||||
use grin_api as api;
|
||||
use grin_core as core;
|
||||
use grin_p2p as p2p;
|
||||
use grin_util as util;
|
||||
use std::sync::Arc;
|
||||
use std::{thread, time};
|
||||
|
||||
#[test]
|
||||
fn simple_server_wallet() {
|
||||
init_test_logger();
|
||||
info!("starting simple_server_wallet");
|
||||
let _test_name_dir = "test_servers";
|
||||
core::global::set_mining_mode(core::global::ChainTypes::AutomatedTesting);
|
||||
|
||||
// Run a separate coinbase wallet for coinbase transactions
|
||||
let coinbase_dir = "coinbase_wallet_api";
|
||||
framework::clean_all_output(coinbase_dir);
|
||||
let mut coinbase_config = LocalServerContainerConfig::default();
|
||||
coinbase_config.name = String::from(coinbase_dir);
|
||||
coinbase_config.wallet_validating_node_url = String::from("http://127.0.0.1:40001");
|
||||
coinbase_config.wallet_port = 50002;
|
||||
let coinbase_wallet = Arc::new(Mutex::new(
|
||||
LocalServerContainer::new(coinbase_config).unwrap(),
|
||||
));
|
||||
|
||||
let _ = thread::spawn(move || {
|
||||
let mut w = coinbase_wallet.lock();
|
||||
w.run_wallet(0);
|
||||
});
|
||||
|
||||
// Wait for the wallet to start
|
||||
thread::sleep(time::Duration::from_millis(1000));
|
||||
|
||||
let api_server_one_dir = "api_server_one";
|
||||
framework::clean_all_output(api_server_one_dir);
|
||||
let mut server_config = LocalServerContainerConfig::default();
|
||||
server_config.name = String::from(api_server_one_dir);
|
||||
server_config.p2p_server_port = 40000;
|
||||
server_config.api_server_port = 40001;
|
||||
server_config.start_miner = true;
|
||||
server_config.start_wallet = false;
|
||||
server_config.coinbase_wallet_address =
|
||||
String::from(format!("http://{}:{}", server_config.base_addr, 50002));
|
||||
let mut server_one = LocalServerContainer::new(server_config.clone()).unwrap();
|
||||
|
||||
// Spawn server and let it run for a bit
|
||||
let _ = thread::spawn(move || server_one.run_server(120));
|
||||
|
||||
//Wait for chain to build
|
||||
thread::sleep(time::Duration::from_millis(5000));
|
||||
|
||||
// Starting tests
|
||||
let base_addr = server_config.base_addr;
|
||||
let api_server_port = server_config.api_server_port;
|
||||
|
||||
warn!("Testing chain handler");
|
||||
let tip = get_tip(&base_addr, api_server_port);
|
||||
assert!(tip.is_ok());
|
||||
|
||||
warn!("Testing status handler");
|
||||
let status = get_status(&base_addr, api_server_port);
|
||||
assert!(status.is_ok());
|
||||
|
||||
// Be sure that at least a block is mined by Travis
|
||||
let mut current_tip = get_tip(&base_addr, api_server_port).unwrap();
|
||||
while current_tip.height == 0 {
|
||||
thread::sleep(time::Duration::from_millis(1000));
|
||||
current_tip = get_tip(&base_addr, api_server_port).unwrap();
|
||||
}
|
||||
|
||||
warn!("Testing block handler");
|
||||
let last_block_by_height = get_block_by_height(&base_addr, api_server_port, current_tip.height);
|
||||
assert!(last_block_by_height.is_ok());
|
||||
let last_block_by_height_compact =
|
||||
get_block_by_height_compact(&base_addr, api_server_port, current_tip.height);
|
||||
assert!(last_block_by_height_compact.is_ok());
|
||||
|
||||
let block_hash = current_tip.last_block_pushed;
|
||||
let last_block_by_hash = get_block_by_hash(&base_addr, api_server_port, &block_hash);
|
||||
assert!(last_block_by_hash.is_ok());
|
||||
let last_block_by_hash_compact =
|
||||
get_block_by_hash_compact(&base_addr, api_server_port, &block_hash);
|
||||
assert!(last_block_by_hash_compact.is_ok());
|
||||
|
||||
warn!("Testing chain output handler");
|
||||
let start_height = 0;
|
||||
let end_height = current_tip.height;
|
||||
let outputs_by_height =
|
||||
get_outputs_by_height(&base_addr, api_server_port, start_height, end_height);
|
||||
assert!(outputs_by_height.is_ok());
|
||||
let ids = get_ids_from_block_outputs(outputs_by_height.unwrap());
|
||||
let outputs_by_ids1 = get_outputs_by_ids1(&base_addr, api_server_port, ids.clone());
|
||||
assert!(outputs_by_ids1.is_ok());
|
||||
let outputs_by_ids2 = get_outputs_by_ids2(&base_addr, api_server_port, ids.clone());
|
||||
assert!(outputs_by_ids2.is_ok());
|
||||
|
||||
warn!("Testing txhashset handler");
|
||||
let roots = get_txhashset_roots(&base_addr, api_server_port);
|
||||
assert!(roots.is_ok());
|
||||
let last_10_outputs = get_txhashset_lastoutputs(&base_addr, api_server_port, 0);
|
||||
assert!(last_10_outputs.is_ok());
|
||||
let last_5_outputs = get_txhashset_lastoutputs(&base_addr, api_server_port, 5);
|
||||
assert!(last_5_outputs.is_ok());
|
||||
let last_10_rangeproofs = get_txhashset_lastrangeproofs(&base_addr, api_server_port, 0);
|
||||
assert!(last_10_rangeproofs.is_ok());
|
||||
let last_5_rangeproofs = get_txhashset_lastrangeproofs(&base_addr, api_server_port, 5);
|
||||
assert!(last_5_rangeproofs.is_ok());
|
||||
let last_10_kernels = get_txhashset_lastkernels(&base_addr, api_server_port, 0);
|
||||
assert!(last_10_kernels.is_ok());
|
||||
let last_5_kernels = get_txhashset_lastkernels(&base_addr, api_server_port, 5);
|
||||
assert!(last_5_kernels.is_ok());
|
||||
|
||||
//let some more mining happen, make sure nothing pukes
|
||||
thread::sleep(time::Duration::from_millis(5000));
|
||||
}
|
||||
|
||||
/// Creates 2 servers and test P2P API
|
||||
#[test]
|
||||
fn test_p2p() {
|
||||
init_test_logger();
|
||||
info!("starting test_p2p");
|
||||
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
||||
|
||||
let _test_name_dir = "test_servers";
|
||||
|
||||
// Spawn server and let it run for a bit
|
||||
let server_one_dir = "p2p_server_one";
|
||||
framework::clean_all_output(server_one_dir);
|
||||
let mut server_config_one = LocalServerContainerConfig::default();
|
||||
server_config_one.name = String::from(server_one_dir);
|
||||
server_config_one.p2p_server_port = 40002;
|
||||
server_config_one.api_server_port = 40003;
|
||||
server_config_one.start_miner = false;
|
||||
server_config_one.start_wallet = false;
|
||||
server_config_one.is_seeding = true;
|
||||
let mut server_one = LocalServerContainer::new(server_config_one.clone()).unwrap();
|
||||
let _ = thread::spawn(move || server_one.run_server(120));
|
||||
|
||||
thread::sleep(time::Duration::from_millis(1000));
|
||||
|
||||
// Spawn server and let it run for a bit
|
||||
let server_two_dir = "p2p_server_two";
|
||||
framework::clean_all_output(server_two_dir);
|
||||
let mut server_config_two = LocalServerContainerConfig::default();
|
||||
server_config_two.name = String::from(server_two_dir);
|
||||
server_config_two.p2p_server_port = 40004;
|
||||
server_config_two.api_server_port = 40005;
|
||||
server_config_two.start_miner = false;
|
||||
server_config_two.start_wallet = false;
|
||||
server_config_two.is_seeding = false;
|
||||
let mut server_two = LocalServerContainer::new(server_config_two.clone()).unwrap();
|
||||
server_two.add_peer(format!(
|
||||
"{}:{}",
|
||||
server_config_one.base_addr, server_config_one.p2p_server_port
|
||||
));
|
||||
let _ = thread::spawn(move || server_two.run_server(120));
|
||||
|
||||
// Let them do the handshake
|
||||
thread::sleep(time::Duration::from_millis(2000));
|
||||
|
||||
// Starting tests
|
||||
warn!("Starting P2P Tests");
|
||||
let base_addr = server_config_one.base_addr;
|
||||
let api_server_port = server_config_one.api_server_port;
|
||||
|
||||
// Check that peer all is also working
|
||||
let mut peers_all = get_all_peers(&base_addr, api_server_port);
|
||||
assert!(peers_all.is_ok());
|
||||
let pall = peers_all.unwrap();
|
||||
assert_eq!(pall.len(), 2);
|
||||
|
||||
// Check that when we get peer connected the peer is here
|
||||
let peers_connected = get_connected_peers(&base_addr, api_server_port);
|
||||
assert!(peers_connected.is_ok());
|
||||
let pc = peers_connected.unwrap();
|
||||
assert_eq!(pc.len(), 1);
|
||||
|
||||
// Check that the peer status is Healthy
|
||||
let addr = format!(
|
||||
"{}:{}",
|
||||
server_config_two.base_addr, server_config_two.p2p_server_port
|
||||
);
|
||||
let peer = get_peer(&base_addr, api_server_port, &addr);
|
||||
assert!(peer.is_ok());
|
||||
assert_eq!(peer.unwrap().flags, p2p::State::Healthy);
|
||||
|
||||
// Ban the peer
|
||||
let ban_result = ban_peer(&base_addr, api_server_port, &addr);
|
||||
assert!(ban_result.is_ok());
|
||||
thread::sleep(time::Duration::from_millis(2000));
|
||||
|
||||
// Check its status is banned with get peer
|
||||
let peer = get_peer(&base_addr, api_server_port, &addr);
|
||||
assert!(peer.is_ok());
|
||||
assert_eq!(peer.unwrap().flags, p2p::State::Banned);
|
||||
|
||||
// Check from peer all
|
||||
peers_all = get_all_peers(&base_addr, api_server_port);
|
||||
assert!(peers_all.is_ok());
|
||||
assert_eq!(peers_all.unwrap().len(), 2);
|
||||
|
||||
// Unban
|
||||
let unban_result = unban_peer(&base_addr, api_server_port, &addr);
|
||||
assert!(unban_result.is_ok());
|
||||
|
||||
// Check from peer connected
|
||||
let peers_connected = get_connected_peers(&base_addr, api_server_port);
|
||||
assert!(peers_connected.is_ok());
|
||||
assert_eq!(peers_connected.unwrap().len(), 0);
|
||||
|
||||
// Check its status is healthy with get peer
|
||||
let peer = get_peer(&base_addr, api_server_port, &addr);
|
||||
assert!(peer.is_ok());
|
||||
assert_eq!(peer.unwrap().flags, p2p::State::Healthy);
|
||||
}
|
||||
|
||||
// Tip handler function
|
||||
fn get_tip(base_addr: &String, api_server_port: u16) -> Result<api::Tip, Error> {
|
||||
let url = format!("http://{}:{}/v1/chain", base_addr, api_server_port);
|
||||
api::client::get::<api::Tip>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
// Status handler function
|
||||
fn get_status(base_addr: &String, api_server_port: u16) -> Result<api::Status, Error> {
|
||||
let url = format!("http://{}:{}/v1/status", base_addr, api_server_port);
|
||||
api::client::get::<api::Status>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
// Block handler functions
|
||||
fn get_block_by_height(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
height: u64,
|
||||
) -> Result<api::BlockPrintable, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/blocks/{}",
|
||||
base_addr, api_server_port, height
|
||||
);
|
||||
api::client::get::<api::BlockPrintable>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_block_by_height_compact(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
height: u64,
|
||||
) -> Result<api::CompactBlockPrintable, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/blocks/{}?compact",
|
||||
base_addr, api_server_port, height
|
||||
);
|
||||
api::client::get::<api::CompactBlockPrintable>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_block_by_hash(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
block_hash: &String,
|
||||
) -> Result<api::BlockPrintable, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/blocks/{}",
|
||||
base_addr, api_server_port, block_hash
|
||||
);
|
||||
api::client::get::<api::BlockPrintable>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_block_by_hash_compact(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
block_hash: &String,
|
||||
) -> Result<api::CompactBlockPrintable, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/blocks/{}?compact",
|
||||
base_addr, api_server_port, block_hash
|
||||
);
|
||||
api::client::get::<api::CompactBlockPrintable>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
// Chain output handler functions
|
||||
fn get_outputs_by_ids1(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
ids: Vec<String>,
|
||||
) -> Result<Vec<api::Output>, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/chain/outputs/byids?id={}",
|
||||
base_addr,
|
||||
api_server_port,
|
||||
ids.join(",")
|
||||
);
|
||||
api::client::get::<Vec<api::Output>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_outputs_by_ids2(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
ids: Vec<String>,
|
||||
) -> Result<Vec<api::Output>, Error> {
|
||||
let mut ids_string: String = String::from("");
|
||||
for id in ids {
|
||||
ids_string = ids_string + "?id=" + &id;
|
||||
}
|
||||
let ids_string = String::from(&ids_string[1..ids_string.len()]);
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/chain/outputs/byids?{}",
|
||||
base_addr, api_server_port, ids_string
|
||||
);
|
||||
api::client::get::<Vec<api::Output>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_outputs_by_height(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
) -> Result<Vec<api::BlockOutputs>, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/chain/outputs/byheight?start_height={}&end_height={}",
|
||||
base_addr, api_server_port, start_height, end_height
|
||||
);
|
||||
api::client::get::<Vec<api::BlockOutputs>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
// TxHashSet handler functions
|
||||
fn get_txhashset_roots(base_addr: &String, api_server_port: u16) -> Result<api::TxHashSet, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/txhashset/roots",
|
||||
base_addr, api_server_port
|
||||
);
|
||||
api::client::get::<api::TxHashSet>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_txhashset_lastoutputs(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
n: u64,
|
||||
) -> Result<Vec<api::TxHashSetNode>, Error> {
|
||||
let url: String;
|
||||
if n == 0 {
|
||||
url = format!(
|
||||
"http://{}:{}/v1/txhashset/lastoutputs",
|
||||
base_addr, api_server_port
|
||||
);
|
||||
} else {
|
||||
url = format!(
|
||||
"http://{}:{}/v1/txhashset/lastoutputs?n={}",
|
||||
base_addr, api_server_port, n
|
||||
);
|
||||
}
|
||||
api::client::get::<Vec<api::TxHashSetNode>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_txhashset_lastrangeproofs(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
n: u64,
|
||||
) -> Result<Vec<api::TxHashSetNode>, Error> {
|
||||
let url: String;
|
||||
if n == 0 {
|
||||
url = format!(
|
||||
"http://{}:{}/v1/txhashset/lastrangeproofs",
|
||||
base_addr, api_server_port
|
||||
);
|
||||
} else {
|
||||
url = format!(
|
||||
"http://{}:{}/v1/txhashset/lastrangeproofs?n={}",
|
||||
base_addr, api_server_port, n
|
||||
);
|
||||
}
|
||||
api::client::get::<Vec<api::TxHashSetNode>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
fn get_txhashset_lastkernels(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
n: u64,
|
||||
) -> Result<Vec<api::TxHashSetNode>, Error> {
|
||||
let url: String;
|
||||
if n == 0 {
|
||||
url = format!(
|
||||
"http://{}:{}/v1/txhashset/lastkernels",
|
||||
base_addr, api_server_port
|
||||
);
|
||||
} else {
|
||||
url = format!(
|
||||
"http://{}:{}/v1/txhashset/lastkernels?n={}",
|
||||
base_addr, api_server_port, n
|
||||
);
|
||||
}
|
||||
api::client::get::<Vec<api::TxHashSetNode>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
// Helper function to get a vec of commitment output ids from a vec of block
|
||||
// outputs
|
||||
fn get_ids_from_block_outputs(block_outputs: Vec<api::BlockOutputs>) -> Vec<String> {
|
||||
let mut ids: Vec<String> = Vec::new();
|
||||
for block_output in block_outputs {
|
||||
let outputs = &block_output.outputs;
|
||||
for output in outputs {
|
||||
ids.push(util::to_hex(output.clone().commit.0.to_vec()));
|
||||
}
|
||||
}
|
||||
ids.into_iter().take(100).collect()
|
||||
}
|
||||
|
||||
pub fn ban_peer(base_addr: &String, api_server_port: u16, peer_addr: &String) -> Result<(), Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/peers/{}/ban",
|
||||
base_addr, api_server_port, peer_addr
|
||||
);
|
||||
api::client::post_no_ret(url.as_str(), None, &"").map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
pub fn unban_peer(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
peer_addr: &String,
|
||||
) -> Result<(), Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/peers/{}/unban",
|
||||
base_addr, api_server_port, peer_addr
|
||||
);
|
||||
api::client::post_no_ret(url.as_str(), None, &"").map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
pub fn get_peer(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
peer_addr: &String,
|
||||
) -> Result<p2p::PeerData, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/peers/{}",
|
||||
base_addr, api_server_port, peer_addr
|
||||
);
|
||||
api::client::get::<p2p::PeerData>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
pub fn get_connected_peers(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
) -> Result<Vec<p2p::types::PeerInfoDisplay>, Error> {
|
||||
let url = format!(
|
||||
"http://{}:{}/v1/peers/connected",
|
||||
base_addr, api_server_port
|
||||
);
|
||||
api::client::get::<Vec<p2p::types::PeerInfoDisplay>>(url.as_str(), None)
|
||||
.map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
pub fn get_all_peers(
|
||||
base_addr: &String,
|
||||
api_server_port: u16,
|
||||
) -> Result<Vec<p2p::PeerData>, Error> {
|
||||
let url = format!("http://{}:{}/v1/peers/all", base_addr, api_server_port);
|
||||
api::client::get::<Vec<p2p::PeerData>>(url.as_str(), None).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
/// Error type wrapping underlying module errors.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Error originating from HTTP API calls.
|
||||
API(api::Error),
|
||||
}
|
157
integration/tests/dandelion.rs
Normal file
157
integration/tests/dandelion.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright 2018 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod framework;
|
||||
|
||||
use self::util::Mutex;
|
||||
use crate::framework::{LocalServerContainer, LocalServerContainerConfig};
|
||||
use grin_core as core;
|
||||
use grin_util as util;
|
||||
use std::sync::Arc;
|
||||
use std::{thread, time};
|
||||
|
||||
/// Start 1 node mining, 1 non mining node and two wallets.
|
||||
/// Then send a transaction from one wallet to another and propagate it a stem
|
||||
/// transaction but without stem relay and check if the transaction is still
|
||||
/// broadcasted.
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_dandelion_timeout() {
|
||||
let test_name_dir = "test_dandelion_timeout";
|
||||
core::global::set_mining_mode(core::global::ChainTypes::AutomatedTesting);
|
||||
framework::clean_all_output(test_name_dir);
|
||||
let mut log_config = util::LoggingConfig::default();
|
||||
//log_config.stdout_log_level = util::LogLevel::Trace;
|
||||
log_config.stdout_log_level = util::LogLevel::Info;
|
||||
//init_logger(Some(log_config));
|
||||
util::init_test_logger();
|
||||
|
||||
// Run a separate coinbase wallet for coinbase transactions
|
||||
let mut coinbase_config = LocalServerContainerConfig::default();
|
||||
coinbase_config.name = String::from("coinbase_wallet");
|
||||
coinbase_config.wallet_validating_node_url = String::from("http://127.0.0.1:30001");
|
||||
coinbase_config.wallet_port = 10002;
|
||||
let coinbase_wallet = Arc::new(Mutex::new(
|
||||
LocalServerContainer::new(coinbase_config).unwrap(),
|
||||
));
|
||||
let coinbase_wallet_config = { coinbase_wallet.lock().wallet_config.clone() };
|
||||
|
||||
let coinbase_seed = LocalServerContainer::get_wallet_seed(&coinbase_wallet_config);
|
||||
|
||||
let _ = thread::spawn(move || {
|
||||
let mut w = coinbase_wallet.lock();
|
||||
w.run_wallet(0);
|
||||
});
|
||||
|
||||
let mut recp_config = LocalServerContainerConfig::default();
|
||||
recp_config.name = String::from("target_wallet");
|
||||
recp_config.wallet_validating_node_url = String::from("http://127.0.0.1:30001");
|
||||
recp_config.wallet_port = 20002;
|
||||
let target_wallet = Arc::new(Mutex::new(LocalServerContainer::new(recp_config).unwrap()));
|
||||
let target_wallet_cloned = target_wallet.clone();
|
||||
let recp_wallet_config = { target_wallet.lock().wallet_config.clone() };
|
||||
|
||||
let recp_seed = LocalServerContainer::get_wallet_seed(&recp_wallet_config);
|
||||
//Start up a second wallet, to receive
|
||||
let _ = thread::spawn(move || {
|
||||
let mut w = target_wallet_cloned.lock();
|
||||
w.run_wallet(0);
|
||||
});
|
||||
|
||||
// Spawn server and let it run for a bit
|
||||
let mut server_one_config = LocalServerContainerConfig::default();
|
||||
server_one_config.name = String::from("server_one");
|
||||
server_one_config.p2p_server_port = 30000;
|
||||
server_one_config.api_server_port = 30001;
|
||||
server_one_config.start_miner = true;
|
||||
server_one_config.start_wallet = false;
|
||||
server_one_config.is_seeding = false;
|
||||
server_one_config.coinbase_wallet_address =
|
||||
String::from(format!("http://{}:{}", server_one_config.base_addr, 10002));
|
||||
let mut server_one = LocalServerContainer::new(server_one_config).unwrap();
|
||||
|
||||
let mut server_two_config = LocalServerContainerConfig::default();
|
||||
server_two_config.name = String::from("server_two");
|
||||
server_two_config.p2p_server_port = 40000;
|
||||
server_two_config.api_server_port = 40001;
|
||||
server_two_config.start_miner = false;
|
||||
server_two_config.start_wallet = false;
|
||||
server_two_config.is_seeding = true;
|
||||
let mut server_two = LocalServerContainer::new(server_two_config.clone()).unwrap();
|
||||
|
||||
server_one.add_peer(format!(
|
||||
"{}:{}",
|
||||
server_two_config.base_addr, server_two_config.p2p_server_port
|
||||
));
|
||||
|
||||
// Spawn servers and let them run for a bit
|
||||
let _ = thread::spawn(move || {
|
||||
server_two.run_server(120);
|
||||
});
|
||||
|
||||
// Wait for the first server to start
|
||||
thread::sleep(time::Duration::from_millis(5000));
|
||||
|
||||
let _ = thread::spawn(move || {
|
||||
server_one.run_server(120);
|
||||
});
|
||||
|
||||
// Let them do a handshake and properly update their peer relay
|
||||
thread::sleep(time::Duration::from_millis(30000));
|
||||
|
||||
//Wait until we have some funds to send
|
||||
let mut coinbase_info =
|
||||
LocalServerContainer::get_wallet_info(&coinbase_wallet_config, &coinbase_seed);
|
||||
let mut slept_time = 0;
|
||||
while coinbase_info.amount_currently_spendable < 100000000000 {
|
||||
thread::sleep(time::Duration::from_millis(500));
|
||||
slept_time += 500;
|
||||
if slept_time > 10000 {
|
||||
panic!("Coinbase not confirming in time");
|
||||
}
|
||||
coinbase_info =
|
||||
LocalServerContainer::get_wallet_info(&coinbase_wallet_config, &coinbase_seed);
|
||||
}
|
||||
|
||||
warn!("Sending 50 Grins to recipient wallet");
|
||||
|
||||
// Sending stem transaction
|
||||
LocalServerContainer::send_amount_to(
|
||||
&coinbase_wallet_config,
|
||||
"50.00",
|
||||
1,
|
||||
"not_all",
|
||||
"http://127.0.0.1:20002",
|
||||
false,
|
||||
);
|
||||
|
||||
let coinbase_info =
|
||||
LocalServerContainer::get_wallet_info(&coinbase_wallet_config, &coinbase_seed);
|
||||
println!("Coinbase wallet info: {:?}", coinbase_info);
|
||||
|
||||
let recipient_info = LocalServerContainer::get_wallet_info(&recp_wallet_config, &recp_seed);
|
||||
|
||||
// The transaction should be waiting in the node stempool thus cannot be mined.
|
||||
println!("Recipient wallet info: {:?}", recipient_info);
|
||||
assert!(recipient_info.amount_awaiting_confirmation == 50000000000);
|
||||
|
||||
// Wait for stem timeout
|
||||
thread::sleep(time::Duration::from_millis(35000));
|
||||
println!("Recipient wallet info: {:?}", recipient_info);
|
||||
let recipient_info = LocalServerContainer::get_wallet_info(&recp_wallet_config, &recp_seed);
|
||||
assert!(recipient_info.amount_currently_spendable == 50000000000);
|
||||
}
|
678
integration/tests/framework.rs
Normal file
678
integration/tests/framework.rs
Normal file
|
@ -0,0 +1,678 @@
|
|||
// Copyright 2018 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extern crate grin_apiwallet as apiwallet;
|
||||
extern crate grin_libwallet as libwallet;
|
||||
extern crate grin_refwallet as wallet;
|
||||
extern crate grin_wallet_config as wallet_config;
|
||||
|
||||
use self::keychain::Keychain;
|
||||
use self::util::Mutex;
|
||||
use self::wallet::{HTTPNodeClient, HTTPWalletCommAdapter, LMDBBackend};
|
||||
use self::wallet_config::WalletConfig;
|
||||
use blake2_rfc as blake2;
|
||||
use grin_api as api;
|
||||
use grin_core as core;
|
||||
use grin_keychain as keychain;
|
||||
use grin_p2p as p2p;
|
||||
use grin_servers as servers;
|
||||
use grin_util as util;
|
||||
use std::default::Default;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::{fs, thread, time};
|
||||
|
||||
/// Just removes all results from previous runs
|
||||
pub fn clean_all_output(test_name_dir: &str) {
|
||||
let target_dir = format!("target/tmp/{}", test_name_dir);
|
||||
if let Err(e) = fs::remove_dir_all(target_dir) {
|
||||
println!("can't remove output from previous test :{}, may be ok", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors that can be returned by LocalServerContainer
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Error {
|
||||
Internal(String),
|
||||
Argument(String),
|
||||
NotFound,
|
||||
}
|
||||
|
||||
/// All-in-one server configuration struct, for convenience
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct LocalServerContainerConfig {
|
||||
// user friendly name for the server, also denotes what dir
|
||||
// the data files will appear in
|
||||
pub name: String,
|
||||
|
||||
// Base IP address
|
||||
pub base_addr: String,
|
||||
|
||||
// Port the server (p2p) is running on
|
||||
pub p2p_server_port: u16,
|
||||
|
||||
// Port the API server is running on
|
||||
pub api_server_port: u16,
|
||||
|
||||
// Port the wallet server is running on
|
||||
pub wallet_port: u16,
|
||||
|
||||
// Port the wallet owner API is running on
|
||||
pub owner_port: u16,
|
||||
|
||||
// Whether to include the foreign API endpoints in the owner API
|
||||
pub owner_api_include_foreign: bool,
|
||||
|
||||
// Whether we're going to mine
|
||||
pub start_miner: bool,
|
||||
|
||||
// time in millis by which to artificially slow down the mining loop
|
||||
// in this container
|
||||
pub miner_slowdown_in_millis: u64,
|
||||
|
||||
// Whether we're going to run a wallet as well,
|
||||
// can use same server instance as a validating node for convenience
|
||||
pub start_wallet: bool,
|
||||
|
||||
// address of a server to use as a seed
|
||||
pub seed_addr: String,
|
||||
|
||||
// keep track of whether this server is supposed to be seeding
|
||||
pub is_seeding: bool,
|
||||
|
||||
// Whether to burn mining rewards
|
||||
pub burn_mining_rewards: bool,
|
||||
|
||||
// full address to send coinbase rewards to
|
||||
pub coinbase_wallet_address: String,
|
||||
|
||||
// When running a wallet, the address to check inputs and send
|
||||
// finalised transactions to,
|
||||
pub wallet_validating_node_url: String,
|
||||
}
|
||||
|
||||
/// Default server config
|
||||
impl Default for LocalServerContainerConfig {
|
||||
fn default() -> LocalServerContainerConfig {
|
||||
LocalServerContainerConfig {
|
||||
name: String::from("test_host"),
|
||||
base_addr: String::from("127.0.0.1"),
|
||||
api_server_port: 13413,
|
||||
p2p_server_port: 13414,
|
||||
wallet_port: 13415,
|
||||
owner_port: 13420,
|
||||
owner_api_include_foreign: false,
|
||||
seed_addr: String::from(""),
|
||||
is_seeding: false,
|
||||
start_miner: false,
|
||||
start_wallet: false,
|
||||
burn_mining_rewards: false,
|
||||
coinbase_wallet_address: String::from(""),
|
||||
wallet_validating_node_url: String::from(""),
|
||||
miner_slowdown_in_millis: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A top-level container to hold everything that might be running
|
||||
/// on a server, i.e. server, wallet in send or receive mode
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct LocalServerContainer {
|
||||
// Configuration
|
||||
config: LocalServerContainerConfig,
|
||||
|
||||
// Structure of references to the
|
||||
// internal server data
|
||||
pub p2p_server_stats: Option<servers::ServerStats>,
|
||||
|
||||
// The API server instance
|
||||
api_server: Option<api::ApiServer>,
|
||||
|
||||
// whether the server is running
|
||||
pub server_is_running: bool,
|
||||
|
||||
// Whether the server is mining
|
||||
pub server_is_mining: bool,
|
||||
|
||||
// Whether the server is also running a wallet
|
||||
// Not used if running wallet without server
|
||||
pub wallet_is_running: bool,
|
||||
|
||||
// the list of peers to connect to
|
||||
pub peer_list: Vec<String>,
|
||||
|
||||
// base directory for the server instance
|
||||
pub working_dir: String,
|
||||
|
||||
// Wallet configuration
|
||||
pub wallet_config: WalletConfig,
|
||||
}
|
||||
|
||||
impl LocalServerContainer {
|
||||
/// Create a new local server container with defaults, with the given name
|
||||
/// all related files will be created in the directory
|
||||
/// target/tmp/{name}
|
||||
|
||||
pub fn new(config: LocalServerContainerConfig) -> Result<LocalServerContainer, Error> {
|
||||
let working_dir = format!("target/tmp/{}", config.name);
|
||||
let mut wallet_config = WalletConfig::default();
|
||||
|
||||
wallet_config.api_listen_port = config.wallet_port;
|
||||
wallet_config.check_node_api_http_addr = config.wallet_validating_node_url.clone();
|
||||
wallet_config.owner_api_include_foreign = Some(config.owner_api_include_foreign);
|
||||
wallet_config.data_file_dir = working_dir.clone();
|
||||
Ok(LocalServerContainer {
|
||||
config: config,
|
||||
p2p_server_stats: None,
|
||||
api_server: None,
|
||||
server_is_running: false,
|
||||
server_is_mining: false,
|
||||
wallet_is_running: false,
|
||||
working_dir: working_dir,
|
||||
peer_list: Vec::new(),
|
||||
wallet_config: wallet_config,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_server(&mut self, duration_in_seconds: u64) -> servers::Server {
|
||||
let api_addr = format!("{}:{}", self.config.base_addr, self.config.api_server_port);
|
||||
|
||||
let mut seeding_type = p2p::Seeding::None;
|
||||
let mut seeds = Vec::new();
|
||||
|
||||
if self.config.seed_addr.len() > 0 {
|
||||
seeding_type = p2p::Seeding::List;
|
||||
seeds = vec![self.config.seed_addr.to_string()];
|
||||
}
|
||||
|
||||
let s = servers::Server::new(servers::ServerConfig {
|
||||
api_http_addr: api_addr,
|
||||
api_secret_path: None,
|
||||
db_root: format!("{}/.grin", self.working_dir),
|
||||
p2p_config: p2p::P2PConfig {
|
||||
port: self.config.p2p_server_port,
|
||||
seeds: Some(seeds),
|
||||
seeding_type: seeding_type,
|
||||
..p2p::P2PConfig::default()
|
||||
},
|
||||
chain_type: core::global::ChainTypes::AutomatedTesting,
|
||||
skip_sync_wait: Some(true),
|
||||
stratum_mining_config: None,
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self.p2p_server_stats = Some(s.get_server_stats().unwrap());
|
||||
|
||||
let mut wallet_url = None;
|
||||
|
||||
if self.config.start_wallet == true {
|
||||
self.run_wallet(duration_in_seconds + 5);
|
||||
// give a second to start wallet before continuing
|
||||
thread::sleep(time::Duration::from_millis(1000));
|
||||
wallet_url = Some(format!(
|
||||
"http://{}:{}",
|
||||
self.config.base_addr, self.config.wallet_port
|
||||
));
|
||||
}
|
||||
|
||||
if self.config.start_miner == true {
|
||||
println!(
|
||||
"starting test Miner on port {}",
|
||||
self.config.p2p_server_port
|
||||
);
|
||||
s.start_test_miner(wallet_url, s.stop_state.clone());
|
||||
}
|
||||
|
||||
for p in &mut self.peer_list {
|
||||
println!("{} connecting to peer: {}", self.config.p2p_server_port, p);
|
||||
let _ = s.connect_peer(p.parse().unwrap());
|
||||
}
|
||||
|
||||
if self.wallet_is_running {
|
||||
self.stop_wallet();
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
/// Make a wallet for use in test endpoints (run_wallet and run_owner).
|
||||
fn make_wallet_for_tests(
|
||||
&mut self,
|
||||
) -> Arc<Mutex<LMDBBackend<HTTPNodeClient, keychain::ExtKeychain>>> {
|
||||
// URL on which to start the wallet listener (i.e. api server)
|
||||
let _url = format!("{}:{}", self.config.base_addr, self.config.wallet_port);
|
||||
|
||||
// Just use the name of the server for a seed for now
|
||||
let seed = format!("{}", self.config.name);
|
||||
|
||||
let _seed = blake2::blake2b::blake2b(32, &[], seed.as_bytes());
|
||||
|
||||
println!(
|
||||
"Starting the Grin wallet receiving daemon on {} ",
|
||||
self.config.wallet_port
|
||||
);
|
||||
|
||||
self.wallet_config = WalletConfig::default();
|
||||
|
||||
self.wallet_config.api_listen_port = self.config.wallet_port;
|
||||
self.wallet_config.check_node_api_http_addr =
|
||||
self.config.wallet_validating_node_url.clone();
|
||||
self.wallet_config.data_file_dir = self.working_dir.clone();
|
||||
self.wallet_config.owner_api_include_foreign = Some(self.config.owner_api_include_foreign);
|
||||
|
||||
let _ = fs::create_dir_all(self.wallet_config.clone().data_file_dir);
|
||||
let r = wallet::WalletSeed::init_file(&self.wallet_config, 32, None, "");
|
||||
|
||||
let client_n = HTTPNodeClient::new(&self.wallet_config.check_node_api_http_addr, None);
|
||||
|
||||
if let Err(_e) = r {
|
||||
//panic!("Error initializing wallet seed: {}", e);
|
||||
}
|
||||
|
||||
let wallet: LMDBBackend<HTTPNodeClient, keychain::ExtKeychain> =
|
||||
LMDBBackend::new(self.wallet_config.clone(), "", client_n).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating wallet: {:?} Config: {:?}",
|
||||
e, self.wallet_config
|
||||
)
|
||||
});
|
||||
|
||||
Arc::new(Mutex::new(wallet))
|
||||
}
|
||||
|
||||
/// Starts a wallet daemon to receive
|
||||
pub fn run_wallet(&mut self, _duration_in_mills: u64) {
|
||||
let wallet = self.make_wallet_for_tests();
|
||||
|
||||
wallet::controller::foreign_listener(wallet, &self.wallet_config.api_listen_addr(), None)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating wallet listener: {:?} Config: {:?}",
|
||||
e, self.wallet_config
|
||||
)
|
||||
});
|
||||
|
||||
self.wallet_is_running = true;
|
||||
}
|
||||
|
||||
/// Starts a wallet owner daemon
|
||||
#[allow(dead_code)]
|
||||
pub fn run_owner(&mut self) {
|
||||
let wallet = self.make_wallet_for_tests();
|
||||
|
||||
// WalletConfig doesn't allow changing the owner API path, so we build
|
||||
// the path ourselves
|
||||
let owner_listen_addr = format!("127.0.0.1:{}", self.config.owner_port);
|
||||
|
||||
wallet::controller::owner_listener(
|
||||
wallet,
|
||||
&owner_listen_addr,
|
||||
None,
|
||||
None,
|
||||
self.wallet_config.owner_api_include_foreign.clone(),
|
||||
)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error creating wallet owner listener: {:?} Config: {:?}",
|
||||
e, self.wallet_config
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_wallet_seed(config: &WalletConfig) -> wallet::WalletSeed {
|
||||
let _ = fs::create_dir_all(config.clone().data_file_dir);
|
||||
wallet::WalletSeed::init_file(config, 32, None, "").unwrap();
|
||||
let wallet_seed =
|
||||
wallet::WalletSeed::from_file(config, "").expect("Failed to read wallet seed file.");
|
||||
wallet_seed
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_wallet_info(
|
||||
config: &WalletConfig,
|
||||
wallet_seed: &wallet::WalletSeed,
|
||||
) -> wallet::WalletInfo {
|
||||
let keychain: keychain::ExtKeychain = wallet_seed
|
||||
.derive_keychain(false)
|
||||
.expect("Failed to derive keychain from seed file and passphrase.");
|
||||
let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None);
|
||||
let mut wallet = LMDBBackend::new(config.clone(), "", client_n)
|
||||
.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);
|
||||
libwallet::internal::updater::retrieve_info(&mut wallet, &parent_id, 1).unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn send_amount_to(
|
||||
config: &WalletConfig,
|
||||
amount: &str,
|
||||
minimum_confirmations: u64,
|
||||
selection_strategy: &str,
|
||||
dest: &str,
|
||||
_fluff: bool,
|
||||
) {
|
||||
let amount = core::core::amount_from_hr_string(amount)
|
||||
.expect("Could not parse amount as a number with optional decimal point.");
|
||||
|
||||
let wallet_seed =
|
||||
wallet::WalletSeed::from_file(config, "").expect("Failed to read wallet seed file.");
|
||||
|
||||
let keychain: keychain::ExtKeychain = wallet_seed
|
||||
.derive_keychain(false)
|
||||
.expect("Failed to derive keychain from seed file and passphrase.");
|
||||
|
||||
let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None);
|
||||
let client_w = HTTPWalletCommAdapter::new();
|
||||
|
||||
let max_outputs = 500;
|
||||
let change_outputs = 1;
|
||||
|
||||
let mut wallet = LMDBBackend::new(config.clone(), "", client_n)
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
|
||||
wallet.keychain = Some(keychain);
|
||||
let _ = wallet::controller::owner_single_use(Arc::new(Mutex::new(wallet)), |api| {
|
||||
let (mut slate, lock_fn) = api.initiate_tx(
|
||||
None,
|
||||
amount,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
change_outputs,
|
||||
selection_strategy == "all",
|
||||
None,
|
||||
)?;
|
||||
slate = client_w.send_tx_sync(dest, &slate)?;
|
||||
api.finalize_tx(&mut slate)?;
|
||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
println!(
|
||||
"Tx sent: {} grin to {} (strategy '{}')",
|
||||
core::core::amount_to_hr_string(amount, false),
|
||||
dest,
|
||||
selection_strategy,
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
|
||||
}
|
||||
|
||||
/// Stops the running wallet server
|
||||
pub fn stop_wallet(&mut self) {
|
||||
println!("Stop wallet!");
|
||||
let api_server = self.api_server.as_mut().unwrap();
|
||||
api_server.stop();
|
||||
}
|
||||
|
||||
/// Adds a peer to this server to connect to upon running
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn add_peer(&mut self, addr: String) {
|
||||
self.peer_list.push(addr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration values for container pool
|
||||
|
||||
pub struct LocalServerContainerPoolConfig {
|
||||
// Base name to append to all the servers in this pool
|
||||
pub base_name: String,
|
||||
|
||||
// Base http address for all of the servers in this pool
|
||||
pub base_http_addr: String,
|
||||
|
||||
// Base port server for all of the servers in this pool
|
||||
// Increment the number by 1 for each new server
|
||||
pub base_p2p_port: u16,
|
||||
|
||||
// Base api port for all of the servers in this pool
|
||||
// Increment this number by 1 for each new server
|
||||
pub base_api_port: u16,
|
||||
|
||||
// Base wallet port for this server
|
||||
//
|
||||
pub base_wallet_port: u16,
|
||||
|
||||
// Base wallet owner port for this server
|
||||
//
|
||||
pub base_owner_port: u16,
|
||||
|
||||
// How long the servers in the pool are going to run
|
||||
pub run_length_in_seconds: u64,
|
||||
}
|
||||
|
||||
/// Default server config
|
||||
///
|
||||
impl Default for LocalServerContainerPoolConfig {
|
||||
fn default() -> LocalServerContainerPoolConfig {
|
||||
LocalServerContainerPoolConfig {
|
||||
base_name: String::from("test_pool"),
|
||||
base_http_addr: String::from("127.0.0.1"),
|
||||
base_p2p_port: 10000,
|
||||
base_api_port: 11000,
|
||||
base_wallet_port: 12000,
|
||||
base_owner_port: 13000,
|
||||
run_length_in_seconds: 30,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience pool for running many servers simultaneously
|
||||
/// without necessarily having to configure each one manually
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct LocalServerContainerPool {
|
||||
// configuration
|
||||
pub config: LocalServerContainerPoolConfig,
|
||||
|
||||
// keep ahold of all the created servers thread-safely
|
||||
server_containers: Vec<LocalServerContainer>,
|
||||
|
||||
// Keep track of what the last ports a server was opened on
|
||||
next_p2p_port: u16,
|
||||
|
||||
next_api_port: u16,
|
||||
|
||||
next_wallet_port: u16,
|
||||
|
||||
next_owner_port: u16,
|
||||
|
||||
// keep track of whether a seed exists, and pause a bit if so
|
||||
is_seeding: bool,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl LocalServerContainerPool {
|
||||
pub fn new(config: LocalServerContainerPoolConfig) -> LocalServerContainerPool {
|
||||
(LocalServerContainerPool {
|
||||
next_api_port: config.base_api_port,
|
||||
next_p2p_port: config.base_p2p_port,
|
||||
next_wallet_port: config.base_wallet_port,
|
||||
next_owner_port: config.base_owner_port,
|
||||
config: config,
|
||||
server_containers: Vec::new(),
|
||||
is_seeding: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// adds a single server on the next available port
|
||||
/// overriding passed-in values as necessary. Config object is an OUT value
|
||||
/// with
|
||||
/// ports/addresses filled in
|
||||
///
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn create_server(&mut self, server_config: &mut LocalServerContainerConfig) {
|
||||
// If we're calling it this way, need to override these
|
||||
server_config.p2p_server_port = self.next_p2p_port;
|
||||
server_config.api_server_port = self.next_api_port;
|
||||
server_config.wallet_port = self.next_wallet_port;
|
||||
server_config.owner_port = self.next_owner_port;
|
||||
|
||||
server_config.name = String::from(format!(
|
||||
"{}/{}-{}",
|
||||
self.config.base_name, self.config.base_name, server_config.p2p_server_port
|
||||
));
|
||||
|
||||
// Use self as coinbase wallet
|
||||
server_config.coinbase_wallet_address = String::from(format!(
|
||||
"http://{}:{}",
|
||||
server_config.base_addr, server_config.wallet_port
|
||||
));
|
||||
|
||||
self.next_p2p_port += 1;
|
||||
self.next_api_port += 1;
|
||||
self.next_wallet_port += 1;
|
||||
self.next_owner_port += 1;
|
||||
|
||||
if server_config.is_seeding {
|
||||
self.is_seeding = true;
|
||||
}
|
||||
|
||||
let _server_address = format!(
|
||||
"{}:{}",
|
||||
server_config.base_addr, server_config.p2p_server_port
|
||||
);
|
||||
|
||||
let server_container = LocalServerContainer::new(server_config.clone()).unwrap();
|
||||
// self.server_containers.push(server_arc);
|
||||
|
||||
// Create a future that runs the server for however many seconds
|
||||
// collect them all and run them in the run_all_servers
|
||||
let _run_time = self.config.run_length_in_seconds;
|
||||
|
||||
self.server_containers.push(server_container);
|
||||
}
|
||||
|
||||
/// adds n servers, ready to run
|
||||
///
|
||||
///
|
||||
#[allow(dead_code)]
|
||||
pub fn create_servers(&mut self, number: u16) {
|
||||
for _ in 0..number {
|
||||
// self.create_server();
|
||||
}
|
||||
}
|
||||
|
||||
/// runs all servers, and returns a vector of references to the servers
|
||||
/// once they've all been run
|
||||
///
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn run_all_servers(self) -> Arc<Mutex<Vec<servers::Server>>> {
|
||||
let run_length = self.config.run_length_in_seconds;
|
||||
let mut handles = vec![];
|
||||
|
||||
// return handles to all of the servers, wrapped in mutexes, handles, etc
|
||||
let return_containers = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
let is_seeding = self.is_seeding.clone();
|
||||
|
||||
for mut s in self.server_containers {
|
||||
let return_container_ref = return_containers.clone();
|
||||
let handle = thread::spawn(move || {
|
||||
if is_seeding && !s.config.is_seeding {
|
||||
// there's a seed and we're not it, so hang around longer and give the seed
|
||||
// a chance to start
|
||||
thread::sleep(time::Duration::from_millis(2000));
|
||||
}
|
||||
let server_ref = s.run_server(run_length);
|
||||
return_container_ref.lock().push(server_ref);
|
||||
});
|
||||
// Not a big fan of sleeping hack here, but there appears to be a
|
||||
// concurrency issue when creating files in rocksdb that causes
|
||||
// failure if we don't pause a bit before starting the next server
|
||||
thread::sleep(time::Duration::from_millis(500));
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
for handle in handles {
|
||||
match handle.join() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
println!("Error starting server thread: {:?}", e);
|
||||
panic!(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return a much simplified version of the results
|
||||
return_containers.clone()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn connect_all_peers(&mut self) {
|
||||
// just pull out all currently active servers, build a list,
|
||||
// and feed into all servers
|
||||
let mut server_addresses: Vec<String> = Vec::new();
|
||||
for s in &self.server_containers {
|
||||
let server_address = format!("{}:{}", s.config.base_addr, s.config.p2p_server_port);
|
||||
server_addresses.push(server_address);
|
||||
}
|
||||
|
||||
for a in server_addresses {
|
||||
for s in &mut self.server_containers {
|
||||
if format!("{}:{}", s.config.base_addr, s.config.p2p_server_port) != a {
|
||||
s.add_peer(a.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn stop_all_servers(servers: Arc<Mutex<Vec<servers::Server>>>) {
|
||||
let locked_servs = servers.lock();
|
||||
for s in locked_servs.deref() {
|
||||
s.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// Create and return a ServerConfig
|
||||
#[allow(dead_code)]
|
||||
pub fn config(n: u16, test_name_dir: &str, seed_n: u16) -> servers::ServerConfig {
|
||||
servers::ServerConfig {
|
||||
api_http_addr: format!("127.0.0.1:{}", 20000 + n),
|
||||
api_secret_path: None,
|
||||
db_root: format!("target/tmp/{}/grin-sync-{}", test_name_dir, n),
|
||||
p2p_config: p2p::P2PConfig {
|
||||
port: 10000 + n,
|
||||
seeding_type: p2p::Seeding::List,
|
||||
seeds: Some(vec![format!("127.0.0.1:{}", 10000 + seed_n)]),
|
||||
..p2p::P2PConfig::default()
|
||||
},
|
||||
chain_type: core::global::ChainTypes::AutomatedTesting,
|
||||
archive_mode: Some(true),
|
||||
skip_sync_wait: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// return stratum mining config
|
||||
#[allow(dead_code)]
|
||||
pub fn stratum_config() -> servers::common::types::StratumServerConfig {
|
||||
servers::common::types::StratumServerConfig {
|
||||
enable_stratum_server: Some(true),
|
||||
stratum_server_addr: Some(String::from("127.0.0.1:13416")),
|
||||
attempt_time_per_block: 60,
|
||||
minimum_share_difficulty: 1,
|
||||
wallet_listener_url: String::from("http://127.0.0.1:13415"),
|
||||
burn_reward: false,
|
||||
}
|
||||
}
|
1006
integration/tests/simulnet.rs
Normal file
1006
integration/tests/simulnet.rs
Normal file
File diff suppressed because it is too large
Load diff
177
integration/tests/stratum.rs
Normal file
177
integration/tests/stratum.rs
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Copyright 2018 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod framework;
|
||||
|
||||
use self::core::global::{self, ChainTypes};
|
||||
use crate::framework::{config, stratum_config};
|
||||
use bufstream::BufStream;
|
||||
use grin_core as core;
|
||||
use grin_servers as servers;
|
||||
use grin_util as util;
|
||||
use grin_util::{Mutex, StopState};
|
||||
use serde_json::Value;
|
||||
use std::io::prelude::{BufRead, Write};
|
||||
use std::net::TcpStream;
|
||||
use std::process;
|
||||
use std::sync::Arc;
|
||||
use std::{thread, time};
|
||||
|
||||
// Create a grin server, and a stratum server.
|
||||
// Simulate a few JSONRpc requests and verify the results.
|
||||
// Validate disconnected workers
|
||||
// Validate broadcasting new jobs
|
||||
#[test]
|
||||
fn basic_stratum_server() {
|
||||
util::init_test_logger();
|
||||
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
||||
|
||||
let test_name_dir = "stratum_server";
|
||||
framework::clean_all_output(test_name_dir);
|
||||
|
||||
// Create a server
|
||||
let s = servers::Server::new(config(4000, test_name_dir, 0)).unwrap();
|
||||
|
||||
// Get mining config with stratumserver enabled
|
||||
let mut stratum_cfg = stratum_config();
|
||||
stratum_cfg.burn_reward = true;
|
||||
stratum_cfg.attempt_time_per_block = 999;
|
||||
stratum_cfg.enable_stratum_server = Some(true);
|
||||
stratum_cfg.stratum_server_addr = Some(String::from("127.0.0.1:11101"));
|
||||
|
||||
// Start stratum server
|
||||
s.start_stratum_server(stratum_cfg);
|
||||
|
||||
// Wait for stratum server to start and
|
||||
// Verify stratum server accepts connections
|
||||
loop {
|
||||
if let Ok(_stream) = TcpStream::connect("127.0.0.1:11101") {
|
||||
break;
|
||||
} else {
|
||||
thread::sleep(time::Duration::from_millis(500));
|
||||
}
|
||||
// As this stream falls out of scope it will be disconnected
|
||||
}
|
||||
info!("stratum server connected");
|
||||
|
||||
// Create a few new worker connections
|
||||
let mut workers = vec![];
|
||||
for _n in 0..5 {
|
||||
let w = TcpStream::connect("127.0.0.1:11101").unwrap();
|
||||
w.set_nonblocking(true)
|
||||
.expect("Failed to set TcpStream to non-blocking");
|
||||
let stream = BufStream::new(w);
|
||||
workers.push(stream);
|
||||
}
|
||||
assert!(workers.len() == 5);
|
||||
info!("workers length verification ok");
|
||||
|
||||
// Simulate a worker lost connection
|
||||
workers.remove(4);
|
||||
|
||||
// Swallow the genesis block
|
||||
thread::sleep(time::Duration::from_secs(5)); // Wait for the server to broadcast
|
||||
let mut response = String::new();
|
||||
for n in 0..workers.len() {
|
||||
let _result = workers[n].read_line(&mut response);
|
||||
}
|
||||
|
||||
// Verify a few stratum JSONRpc commands
|
||||
// getjobtemplate - expected block template result
|
||||
let mut response = String::new();
|
||||
let job_req = "{\"id\": \"Stratum\", \"jsonrpc\": \"2.0\", \"method\": \"getjobtemplate\"}\n";
|
||||
workers[2].write(job_req.as_bytes()).unwrap();
|
||||
workers[2].flush().unwrap();
|
||||
thread::sleep(time::Duration::from_secs(1)); // Wait for the server to reply
|
||||
match workers[2].read_line(&mut response) {
|
||||
Ok(_) => {
|
||||
let r: Value = serde_json::from_str(&response).unwrap();
|
||||
assert_eq!(r["error"], serde_json::Value::Null);
|
||||
assert_ne!(r["result"], serde_json::Value::Null);
|
||||
}
|
||||
Err(_e) => {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
info!("a few stratum JSONRpc commands verification ok");
|
||||
|
||||
// keepalive - expected "ok" result
|
||||
let mut response = String::new();
|
||||
let job_req = "{\"id\":\"3\",\"jsonrpc\":\"2.0\",\"method\":\"keepalive\"}\n";
|
||||
let ok_resp = "{\"id\":\"3\",\"jsonrpc\":\"2.0\",\"method\":\"keepalive\",\"result\":\"ok\",\"error\":null}\n";
|
||||
workers[2].write(job_req.as_bytes()).unwrap();
|
||||
workers[2].flush().unwrap();
|
||||
thread::sleep(time::Duration::from_secs(1)); // Wait for the server to reply
|
||||
let _st = workers[2].read_line(&mut response);
|
||||
assert_eq!(response.as_str(), ok_resp);
|
||||
info!("keepalive test ok");
|
||||
|
||||
// "doesnotexist" - error expected
|
||||
let mut response = String::new();
|
||||
let job_req = "{\"id\":\"4\",\"jsonrpc\":\"2.0\",\"method\":\"doesnotexist\"}\n";
|
||||
let ok_resp = "{\"id\":\"4\",\"jsonrpc\":\"2.0\",\"method\":\"doesnotexist\",\"result\":null,\"error\":{\"code\":-32601,\"message\":\"Method not found\"}}\n";
|
||||
workers[3].write(job_req.as_bytes()).unwrap();
|
||||
workers[3].flush().unwrap();
|
||||
thread::sleep(time::Duration::from_secs(1)); // Wait for the server to reply
|
||||
let _st = workers[3].read_line(&mut response);
|
||||
assert_eq!(response.as_str(), ok_resp);
|
||||
info!("worker doesnotexist test ok");
|
||||
|
||||
// Verify stratum server and worker stats
|
||||
let stats = s.get_server_stats().unwrap();
|
||||
assert_eq!(stats.stratum_stats.block_height, 1); // just 1 genesis block
|
||||
assert_eq!(stats.stratum_stats.num_workers, 4); // 5 - 1 = 4
|
||||
assert_eq!(stats.stratum_stats.worker_stats[5].is_connected, false); // worker was removed
|
||||
assert_eq!(stats.stratum_stats.worker_stats[1].is_connected, true);
|
||||
info!("stratum server and worker stats verification ok");
|
||||
|
||||
// Start mining blocks
|
||||
let stop = Arc::new(Mutex::new(StopState::new()));
|
||||
s.start_test_miner(None, stop.clone());
|
||||
info!("test miner started");
|
||||
|
||||
// This test is supposed to complete in 3 seconds,
|
||||
// so let's set a timeout on 10s to avoid infinite waiting happened in Travis-CI.
|
||||
let _handler = thread::spawn(|| {
|
||||
thread::sleep(time::Duration::from_secs(10));
|
||||
error!("basic_stratum_server test fail on timeout!");
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
// Simulate a worker lost connection
|
||||
workers.remove(1);
|
||||
|
||||
// Wait for a few mined blocks
|
||||
thread::sleep(time::Duration::from_secs(3));
|
||||
s.stop_test_miner(stop);
|
||||
|
||||
// Verify blocks are being broadcast to workers
|
||||
let expected = String::from("job");
|
||||
let mut jobtemplate = String::new();
|
||||
let _st = workers[2].read_line(&mut jobtemplate);
|
||||
let job_template: Value = serde_json::from_str(&jobtemplate).unwrap();
|
||||
assert_eq!(job_template["method"], expected);
|
||||
info!("blocks broadcasting to workers test ok");
|
||||
|
||||
// Verify stratum server and worker stats
|
||||
let stats = s.get_server_stats().unwrap();
|
||||
assert_eq!(stats.stratum_stats.num_workers, 3); // 5 - 2 = 3
|
||||
assert_eq!(stats.stratum_stats.worker_stats[2].is_connected, false); // worker was removed
|
||||
assert_ne!(stats.stratum_stats.block_height, 1);
|
||||
info!("basic_stratum_server test done and ok.");
|
||||
}
|
Loading…
Reference in a new issue