├── .editorconfig ├── .gitignore ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── README.md ├── doc ├── Makefile ├── make.bat └── source │ ├── conf.py │ └── index.rst ├── rust-toolchain ├── rustfmt.toml └── src ├── agent.rs ├── agent.yml ├── handler.rs ├── hardware_usage.rs ├── logger ├── logger.rs ├── macros.rs └── mod.rs ├── main.rs ├── process ├── binary_update.rs ├── codechain_process.rs ├── fs_util.rs ├── git_update.rs ├── git_util.rs ├── mod.rs ├── rpc.rs └── update.rs ├── rpc ├── api.rs ├── mod.rs ├── router.rs └── types.rs └── types.rs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*.rs] 3 | indent_style=space 4 | indent_size=4 5 | tab_width=8 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=120 10 | insert_final_newline=true 11 | 12 | [*.yml] 13 | indent_style=space 14 | indent_size=4 15 | tab_width=8 16 | end_of_line=lf 17 | charset=utf-8 18 | trim_trailing_whitespace=true 19 | insert_final_newline=true 20 | 21 | [.travis.yml] 22 | indent_style=space 23 | indent_size=2 24 | tab_width=8 25 | end_of_line=lf 26 | charset=utf-8 27 | 28 | [*.json] 29 | indent_style=space 30 | indent_size=2 31 | tab_width=4 32 | end_of_line=lf 33 | charset=utf-8 34 | trim_trailing_whitespace=true 35 | insert_final_newline=true 36 | 37 | 38 | [*.toml] 39 | indent_style=space 40 | indent_size=4 41 | tab_width=8 42 | end_of_line=lf 43 | charset=utf-8 44 | trim_trailing_whitespace=true 45 | insert_final_newline=true 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | doc/build/ 2 | 3 | # Generated by Cargo 4 | **/target/ 5 | 6 | **/*.rs.bk 7 | **/*.iml 8 | .idea/ 9 | /db/ 10 | /snapshot/ 11 | /log/ 12 | /keys/ 13 | 14 | # macOS 15 | .DS_store 16 | .vscode/ 17 | /build/ 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - 1.32.0 4 | install: 5 | - rustup toolchain install nightly-2018-12-06 6 | - rustup component add rustfmt-preview --toolchain nightly-2018-12-06 7 | - rustup component add clippy-preview --toolchain nightly-2018-12-06 8 | before_script: 9 | - cargo fetch --verbose 10 | script: 11 | - cargo +nightly-2018-12-06 fmt -- --check 12 | && RUST_BACKTRACE=1 cargo test --verbose --all 13 | && cargo +nightly-2018-12-06 clippy --all-targets --all-features 14 | matrix: 15 | allow_failures: 16 | - rust: nightly 17 | include: 18 | - os: linux 19 | sudo: required 20 | - os: osx 21 | cache: cargo 22 | git: 23 | depth: 1 24 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "MacTypes-sys" 3 | version = "2.1.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "adler32" 11 | version = "1.0.3" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | 14 | [[package]] 15 | name = "aho-corasick" 16 | version = "0.6.10" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | dependencies = [ 19 | "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 20 | ] 21 | 22 | [[package]] 23 | name = "ansi_term" 24 | version = "0.11.0" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | dependencies = [ 27 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 28 | ] 29 | 30 | [[package]] 31 | name = "arc-swap" 32 | version = "0.1.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | 35 | [[package]] 36 | name = "arrayvec" 37 | version = "0.4.10" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | dependencies = [ 40 | "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 41 | ] 42 | 43 | [[package]] 44 | name = "atty" 45 | version = "0.2.11" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | dependencies = [ 48 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 49 | "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 50 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 51 | ] 52 | 53 | [[package]] 54 | name = "autocfg" 55 | version = "0.1.2" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | 58 | [[package]] 59 | name = "base64" 60 | version = "0.10.1" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | dependencies = [ 63 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 64 | ] 65 | 66 | [[package]] 67 | name = "bitflags" 68 | version = "1.0.4" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | 71 | [[package]] 72 | name = "build_const" 73 | version = "0.2.1" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | 76 | [[package]] 77 | name = "byteorder" 78 | version = "1.3.1" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | 81 | [[package]] 82 | name = "bytes" 83 | version = "0.4.12" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | dependencies = [ 86 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 87 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 88 | ] 89 | 90 | [[package]] 91 | name = "bytesize" 92 | version = "0.1.3" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | 95 | [[package]] 96 | name = "cc" 97 | version = "1.0.31" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | 100 | [[package]] 101 | name = "cfg-if" 102 | version = "0.1.7" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | 105 | [[package]] 106 | name = "chrono" 107 | version = "0.4.6" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | dependencies = [ 110 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 112 | "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 113 | ] 114 | 115 | [[package]] 116 | name = "clap" 117 | version = "2.32.0" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | dependencies = [ 120 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 121 | "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 122 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 123 | "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 124 | "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 125 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 126 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 127 | "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 128 | ] 129 | 130 | [[package]] 131 | name = "cloudabi" 132 | version = "0.0.3" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | dependencies = [ 135 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 136 | ] 137 | 138 | [[package]] 139 | name = "codechain-agent" 140 | version = "0.1.0" 141 | dependencies = [ 142 | "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 143 | "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", 144 | "colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 145 | "crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", 147 | "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", 148 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 149 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 150 | "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 151 | "reopen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 152 | "reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", 153 | "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 154 | "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 155 | "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 156 | "subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", 157 | "sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 158 | "systemstat 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 159 | "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 160 | "ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 161 | ] 162 | 163 | [[package]] 164 | name = "colored" 165 | version = "1.7.0" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | dependencies = [ 168 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 169 | ] 170 | 171 | [[package]] 172 | name = "core-foundation" 173 | version = "0.5.1" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | dependencies = [ 176 | "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 177 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 178 | ] 179 | 180 | [[package]] 181 | name = "core-foundation-sys" 182 | version = "0.5.1" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | dependencies = [ 185 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 186 | ] 187 | 188 | [[package]] 189 | name = "crc" 190 | version = "1.8.1" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | dependencies = [ 193 | "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 194 | ] 195 | 196 | [[package]] 197 | name = "crc32fast" 198 | version = "1.2.0" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 202 | ] 203 | 204 | [[package]] 205 | name = "crossbeam" 206 | version = "0.4.1" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | dependencies = [ 209 | "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 210 | "crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 211 | "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 212 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 213 | ] 214 | 215 | [[package]] 216 | name = "crossbeam-channel" 217 | version = "0.2.6" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | dependencies = [ 220 | "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 221 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 222 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 223 | "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 224 | "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 225 | ] 226 | 227 | [[package]] 228 | name = "crossbeam-deque" 229 | version = "0.2.0" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | dependencies = [ 232 | "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 233 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 234 | ] 235 | 236 | [[package]] 237 | name = "crossbeam-deque" 238 | version = "0.5.2" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | dependencies = [ 241 | "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 242 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 243 | ] 244 | 245 | [[package]] 246 | name = "crossbeam-deque" 247 | version = "0.7.1" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | dependencies = [ 250 | "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 251 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 252 | ] 253 | 254 | [[package]] 255 | name = "crossbeam-epoch" 256 | version = "0.3.1" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | dependencies = [ 259 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 260 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 261 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 262 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 263 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 264 | "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 265 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 266 | ] 267 | 268 | [[package]] 269 | name = "crossbeam-epoch" 270 | version = "0.5.2" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | dependencies = [ 273 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 274 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 275 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 276 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 277 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 278 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 279 | ] 280 | 281 | [[package]] 282 | name = "crossbeam-epoch" 283 | version = "0.6.1" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | dependencies = [ 286 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 287 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 288 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 289 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 290 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 291 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 292 | ] 293 | 294 | [[package]] 295 | name = "crossbeam-epoch" 296 | version = "0.7.1" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | dependencies = [ 299 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 300 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 301 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 302 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 303 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 304 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 305 | ] 306 | 307 | [[package]] 308 | name = "crossbeam-queue" 309 | version = "0.1.2" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | dependencies = [ 312 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 313 | ] 314 | 315 | [[package]] 316 | name = "crossbeam-utils" 317 | version = "0.2.2" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | dependencies = [ 320 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 321 | ] 322 | 323 | [[package]] 324 | name = "crossbeam-utils" 325 | version = "0.5.0" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | 328 | [[package]] 329 | name = "crossbeam-utils" 330 | version = "0.6.5" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | dependencies = [ 333 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 334 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 335 | ] 336 | 337 | [[package]] 338 | name = "dtoa" 339 | version = "0.4.3" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | 342 | [[package]] 343 | name = "either" 344 | version = "1.5.1" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | 347 | [[package]] 348 | name = "encoding_rs" 349 | version = "0.8.17" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | dependencies = [ 352 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 353 | ] 354 | 355 | [[package]] 356 | name = "env_logger" 357 | version = "0.5.13" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | dependencies = [ 360 | "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 361 | "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 362 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 363 | "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 364 | "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 365 | ] 366 | 367 | [[package]] 368 | name = "flate2" 369 | version = "1.0.7" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | dependencies = [ 372 | "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 373 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 374 | "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 375 | ] 376 | 377 | [[package]] 378 | name = "fnv" 379 | version = "1.0.6" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | 382 | [[package]] 383 | name = "foreign-types" 384 | version = "0.3.2" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | dependencies = [ 387 | "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 388 | ] 389 | 390 | [[package]] 391 | name = "foreign-types-shared" 392 | version = "0.1.1" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | 395 | [[package]] 396 | name = "fuchsia-cprng" 397 | version = "0.1.1" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | 400 | [[package]] 401 | name = "fuchsia-zircon" 402 | version = "0.3.3" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | dependencies = [ 405 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 406 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 407 | ] 408 | 409 | [[package]] 410 | name = "fuchsia-zircon-sys" 411 | version = "0.3.3" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | 414 | [[package]] 415 | name = "futures" 416 | version = "0.1.25" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | 419 | [[package]] 420 | name = "futures-cpupool" 421 | version = "0.1.8" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | dependencies = [ 424 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 425 | "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 426 | ] 427 | 428 | [[package]] 429 | name = "h2" 430 | version = "0.1.17" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | dependencies = [ 433 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 434 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 435 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 436 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 437 | "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 438 | "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 439 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 440 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 441 | "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 442 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 443 | ] 444 | 445 | [[package]] 446 | name = "http" 447 | version = "0.1.16" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | dependencies = [ 450 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 451 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 452 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 453 | ] 454 | 455 | [[package]] 456 | name = "httparse" 457 | version = "1.3.3" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | 460 | [[package]] 461 | name = "humantime" 462 | version = "1.2.0" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | dependencies = [ 465 | "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 466 | ] 467 | 468 | [[package]] 469 | name = "hyper" 470 | version = "0.12.25" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | dependencies = [ 473 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 474 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 475 | "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 476 | "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", 477 | "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 478 | "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 479 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 480 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 481 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 482 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 483 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 484 | "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 485 | "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", 486 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 487 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 488 | "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 489 | "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 490 | "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 491 | "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 492 | "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 493 | ] 494 | 495 | [[package]] 496 | name = "hyper-tls" 497 | version = "0.3.2" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | dependencies = [ 500 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 501 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 502 | "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", 503 | "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 504 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 505 | ] 506 | 507 | [[package]] 508 | name = "idna" 509 | version = "0.1.5" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | dependencies = [ 512 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 513 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 514 | "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 515 | ] 516 | 517 | [[package]] 518 | name = "indexmap" 519 | version = "1.0.2" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | 522 | [[package]] 523 | name = "iovec" 524 | version = "0.1.2" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | dependencies = [ 527 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 528 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 529 | ] 530 | 531 | [[package]] 532 | name = "itoa" 533 | version = "0.4.3" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | 536 | [[package]] 537 | name = "jsonrpc-core" 538 | version = "8.0.1" 539 | source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#a1b2bb742ce16d1168669ffb13ffe856e8131228" 540 | dependencies = [ 541 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 542 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 543 | "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 544 | "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 545 | "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 546 | ] 547 | 548 | [[package]] 549 | name = "kernel32-sys" 550 | version = "0.2.2" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | dependencies = [ 553 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 554 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 555 | ] 556 | 557 | [[package]] 558 | name = "lazy_static" 559 | version = "1.3.0" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | 562 | [[package]] 563 | name = "lazycell" 564 | version = "1.2.1" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | 567 | [[package]] 568 | name = "libc" 569 | version = "0.2.50" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | 572 | [[package]] 573 | name = "lock_api" 574 | version = "0.1.5" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | dependencies = [ 577 | "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 578 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 579 | ] 580 | 581 | [[package]] 582 | name = "log" 583 | version = "0.3.9" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | dependencies = [ 586 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 587 | ] 588 | 589 | [[package]] 590 | name = "log" 591 | version = "0.4.6" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | dependencies = [ 594 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 595 | ] 596 | 597 | [[package]] 598 | name = "matches" 599 | version = "0.1.8" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | 602 | [[package]] 603 | name = "memchr" 604 | version = "1.0.2" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | dependencies = [ 607 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 608 | ] 609 | 610 | [[package]] 611 | name = "memchr" 612 | version = "2.2.0" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | 615 | [[package]] 616 | name = "memoffset" 617 | version = "0.2.1" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | 620 | [[package]] 621 | name = "mime" 622 | version = "0.3.13" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | dependencies = [ 625 | "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 626 | ] 627 | 628 | [[package]] 629 | name = "mime_guess" 630 | version = "2.0.0-alpha.6" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | dependencies = [ 633 | "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", 634 | "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", 635 | "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", 636 | "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 637 | ] 638 | 639 | [[package]] 640 | name = "miniz_oxide" 641 | version = "0.2.1" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | dependencies = [ 644 | "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 645 | ] 646 | 647 | [[package]] 648 | name = "miniz_oxide_c_api" 649 | version = "0.2.1" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | dependencies = [ 652 | "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", 653 | "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 654 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 655 | "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 656 | ] 657 | 658 | [[package]] 659 | name = "mio" 660 | version = "0.6.16" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | dependencies = [ 663 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 664 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 665 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 666 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 667 | "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 668 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 669 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 670 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 671 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 672 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 673 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 674 | ] 675 | 676 | [[package]] 677 | name = "mio-extras" 678 | version = "2.0.5" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | dependencies = [ 681 | "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 682 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 683 | "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", 684 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 685 | ] 686 | 687 | [[package]] 688 | name = "miow" 689 | version = "0.2.1" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | dependencies = [ 692 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 693 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 694 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 695 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 696 | ] 697 | 698 | [[package]] 699 | name = "native-tls" 700 | version = "0.2.2" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | dependencies = [ 703 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 704 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 705 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 706 | "openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)", 707 | "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 708 | "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", 709 | "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", 710 | "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 711 | "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 712 | "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 713 | ] 714 | 715 | [[package]] 716 | name = "net2" 717 | version = "0.2.33" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | dependencies = [ 720 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 721 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 722 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 723 | ] 724 | 725 | [[package]] 726 | name = "nodrop" 727 | version = "0.1.13" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | 730 | [[package]] 731 | name = "nom" 732 | version = "3.2.1" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | dependencies = [ 735 | "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 736 | ] 737 | 738 | [[package]] 739 | name = "num-integer" 740 | version = "0.1.39" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | dependencies = [ 743 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 744 | ] 745 | 746 | [[package]] 747 | name = "num-traits" 748 | version = "0.2.6" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | 751 | [[package]] 752 | name = "num_cpus" 753 | version = "1.10.0" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | dependencies = [ 756 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 757 | ] 758 | 759 | [[package]] 760 | name = "openssl" 761 | version = "0.10.20" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | dependencies = [ 764 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 765 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 766 | "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 767 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 768 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 769 | "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", 770 | ] 771 | 772 | [[package]] 773 | name = "openssl-probe" 774 | version = "0.1.2" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | 777 | [[package]] 778 | name = "openssl-sys" 779 | version = "0.9.43" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | dependencies = [ 782 | "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", 783 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 784 | "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", 785 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 786 | "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 787 | ] 788 | 789 | [[package]] 790 | name = "owning_ref" 791 | version = "0.4.0" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | dependencies = [ 794 | "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 795 | ] 796 | 797 | [[package]] 798 | name = "parking_lot" 799 | version = "0.6.4" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | dependencies = [ 802 | "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 803 | "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 804 | ] 805 | 806 | [[package]] 807 | name = "parking_lot" 808 | version = "0.7.1" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | dependencies = [ 811 | "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 812 | "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 813 | ] 814 | 815 | [[package]] 816 | name = "parking_lot_core" 817 | version = "0.3.1" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | dependencies = [ 820 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 821 | "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 822 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 823 | "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 824 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 825 | ] 826 | 827 | [[package]] 828 | name = "parking_lot_core" 829 | version = "0.4.0" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | dependencies = [ 832 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 833 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 834 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 835 | "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 836 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 837 | ] 838 | 839 | [[package]] 840 | name = "percent-encoding" 841 | version = "1.0.1" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | 844 | [[package]] 845 | name = "phf" 846 | version = "0.7.24" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | dependencies = [ 849 | "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", 850 | ] 851 | 852 | [[package]] 853 | name = "phf_codegen" 854 | version = "0.7.24" 855 | source = "registry+https://github.com/rust-lang/crates.io-index" 856 | dependencies = [ 857 | "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", 858 | "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", 859 | ] 860 | 861 | [[package]] 862 | name = "phf_generator" 863 | version = "0.7.24" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | dependencies = [ 866 | "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", 867 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 868 | ] 869 | 870 | [[package]] 871 | name = "phf_shared" 872 | version = "0.7.24" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | dependencies = [ 875 | "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 876 | "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 877 | ] 878 | 879 | [[package]] 880 | name = "pkg-config" 881 | version = "0.3.14" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | 884 | [[package]] 885 | name = "proc-macro2" 886 | version = "0.4.27" 887 | source = "registry+https://github.com/rust-lang/crates.io-index" 888 | dependencies = [ 889 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 890 | ] 891 | 892 | [[package]] 893 | name = "quick-error" 894 | version = "1.2.2" 895 | source = "registry+https://github.com/rust-lang/crates.io-index" 896 | 897 | [[package]] 898 | name = "quote" 899 | version = "0.6.11" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | dependencies = [ 902 | "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 903 | ] 904 | 905 | [[package]] 906 | name = "rand" 907 | version = "0.5.6" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | dependencies = [ 910 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 911 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 912 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 913 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 914 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 915 | ] 916 | 917 | [[package]] 918 | name = "rand" 919 | version = "0.6.5" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | dependencies = [ 922 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 923 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 924 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 925 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 926 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 927 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 928 | "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 929 | "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 930 | "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 931 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 932 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 933 | ] 934 | 935 | [[package]] 936 | name = "rand_chacha" 937 | version = "0.1.1" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | dependencies = [ 940 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 941 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 942 | ] 943 | 944 | [[package]] 945 | name = "rand_core" 946 | version = "0.3.1" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | dependencies = [ 949 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 950 | ] 951 | 952 | [[package]] 953 | name = "rand_core" 954 | version = "0.4.0" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | 957 | [[package]] 958 | name = "rand_hc" 959 | version = "0.1.0" 960 | source = "registry+https://github.com/rust-lang/crates.io-index" 961 | dependencies = [ 962 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 963 | ] 964 | 965 | [[package]] 966 | name = "rand_isaac" 967 | version = "0.1.1" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | dependencies = [ 970 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 971 | ] 972 | 973 | [[package]] 974 | name = "rand_jitter" 975 | version = "0.1.3" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | dependencies = [ 978 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 979 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 980 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 981 | ] 982 | 983 | [[package]] 984 | name = "rand_os" 985 | version = "0.1.3" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | dependencies = [ 988 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 989 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 990 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 991 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 992 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 993 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 994 | ] 995 | 996 | [[package]] 997 | name = "rand_pcg" 998 | version = "0.1.2" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | dependencies = [ 1001 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1002 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1003 | ] 1004 | 1005 | [[package]] 1006 | name = "rand_xorshift" 1007 | version = "0.1.1" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | dependencies = [ 1010 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1011 | ] 1012 | 1013 | [[package]] 1014 | name = "rayon" 1015 | version = "1.0.3" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | dependencies = [ 1018 | "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1019 | "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1020 | "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "rayon-core" 1025 | version = "1.4.1" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | dependencies = [ 1028 | "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1029 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1030 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1031 | "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 1032 | ] 1033 | 1034 | [[package]] 1035 | name = "rdrand" 1036 | version = "0.4.0" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | dependencies = [ 1039 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1040 | ] 1041 | 1042 | [[package]] 1043 | name = "redox_syscall" 1044 | version = "0.1.51" 1045 | source = "registry+https://github.com/rust-lang/crates.io-index" 1046 | 1047 | [[package]] 1048 | name = "redox_termios" 1049 | version = "0.1.1" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | dependencies = [ 1052 | "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", 1053 | ] 1054 | 1055 | [[package]] 1056 | name = "regex" 1057 | version = "1.1.2" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | dependencies = [ 1060 | "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1061 | "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1062 | "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1063 | "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1064 | "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "regex-syntax" 1069 | version = "0.6.5" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | dependencies = [ 1072 | "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 1073 | ] 1074 | 1075 | [[package]] 1076 | name = "remove_dir_all" 1077 | version = "0.5.1" 1078 | source = "registry+https://github.com/rust-lang/crates.io-index" 1079 | dependencies = [ 1080 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1081 | ] 1082 | 1083 | [[package]] 1084 | name = "reopen" 1085 | version = "0.2.2" 1086 | source = "registry+https://github.com/rust-lang/crates.io-index" 1087 | dependencies = [ 1088 | "arc-swap 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1089 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1090 | ] 1091 | 1092 | [[package]] 1093 | name = "reqwest" 1094 | version = "0.9.12" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | dependencies = [ 1097 | "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", 1098 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 1099 | "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", 1100 | "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 1101 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1102 | "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 1103 | "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", 1104 | "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 1105 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1106 | "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", 1107 | "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", 1108 | "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 1109 | "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 1110 | "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 1111 | "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", 1112 | "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", 1113 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1114 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1115 | "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 1116 | "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 1117 | "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1118 | "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "rustc_version" 1123 | version = "0.2.3" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | dependencies = [ 1126 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "ryu" 1131 | version = "0.2.7" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | 1134 | [[package]] 1135 | name = "schannel" 1136 | version = "0.1.15" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | dependencies = [ 1139 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1140 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "scopeguard" 1145 | version = "0.3.3" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | 1148 | [[package]] 1149 | name = "security-framework" 1150 | version = "0.2.2" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | dependencies = [ 1153 | "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1154 | "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1155 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1156 | "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 1157 | ] 1158 | 1159 | [[package]] 1160 | name = "security-framework-sys" 1161 | version = "0.2.3" 1162 | source = "registry+https://github.com/rust-lang/crates.io-index" 1163 | dependencies = [ 1164 | "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1165 | "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1166 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "semver" 1171 | version = "0.9.0" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | dependencies = [ 1174 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "semver-parser" 1179 | version = "0.7.0" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | 1182 | [[package]] 1183 | name = "serde" 1184 | version = "1.0.89" 1185 | source = "registry+https://github.com/rust-lang/crates.io-index" 1186 | 1187 | [[package]] 1188 | name = "serde_derive" 1189 | version = "1.0.89" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | dependencies = [ 1192 | "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 1193 | "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1194 | "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", 1195 | ] 1196 | 1197 | [[package]] 1198 | name = "serde_json" 1199 | version = "1.0.39" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | dependencies = [ 1202 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1203 | "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 1204 | "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "serde_urlencoded" 1209 | version = "0.5.4" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | dependencies = [ 1212 | "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1213 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1214 | "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", 1215 | "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1216 | ] 1217 | 1218 | [[package]] 1219 | name = "sha1" 1220 | version = "0.6.0" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | 1223 | [[package]] 1224 | name = "siphasher" 1225 | version = "0.2.3" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | 1228 | [[package]] 1229 | name = "slab" 1230 | version = "0.4.2" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | 1233 | [[package]] 1234 | name = "smallvec" 1235 | version = "0.6.9" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | 1238 | [[package]] 1239 | name = "stable_deref_trait" 1240 | version = "1.1.1" 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" 1242 | 1243 | [[package]] 1244 | name = "string" 1245 | version = "0.1.3" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | 1248 | [[package]] 1249 | name = "strsim" 1250 | version = "0.7.0" 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" 1252 | 1253 | [[package]] 1254 | name = "subprocess" 1255 | version = "0.1.18" 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" 1257 | dependencies = [ 1258 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 1259 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1260 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1261 | ] 1262 | 1263 | [[package]] 1264 | name = "syn" 1265 | version = "0.15.29" 1266 | source = "registry+https://github.com/rust-lang/crates.io-index" 1267 | dependencies = [ 1268 | "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 1269 | "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 1270 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1271 | ] 1272 | 1273 | [[package]] 1274 | name = "sysinfo" 1275 | version = "0.6.2" 1276 | source = "registry+https://github.com/rust-lang/crates.io-index" 1277 | dependencies = [ 1278 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1279 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1280 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 1281 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1282 | ] 1283 | 1284 | [[package]] 1285 | name = "systemstat" 1286 | version = "0.1.4" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | dependencies = [ 1289 | "bytesize 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 1290 | "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1291 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1292 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1293 | "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1294 | "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 1295 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1296 | ] 1297 | 1298 | [[package]] 1299 | name = "tempfile" 1300 | version = "3.0.7" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | dependencies = [ 1303 | "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1304 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1305 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1306 | "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", 1307 | "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1308 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1309 | ] 1310 | 1311 | [[package]] 1312 | name = "termcolor" 1313 | version = "1.0.4" 1314 | source = "registry+https://github.com/rust-lang/crates.io-index" 1315 | dependencies = [ 1316 | "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1317 | ] 1318 | 1319 | [[package]] 1320 | name = "termion" 1321 | version = "1.5.1" 1322 | source = "registry+https://github.com/rust-lang/crates.io-index" 1323 | dependencies = [ 1324 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1325 | "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", 1326 | "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1327 | ] 1328 | 1329 | [[package]] 1330 | name = "textwrap" 1331 | version = "0.10.0" 1332 | source = "registry+https://github.com/rust-lang/crates.io-index" 1333 | dependencies = [ 1334 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1335 | ] 1336 | 1337 | [[package]] 1338 | name = "thread_local" 1339 | version = "0.3.6" 1340 | source = "registry+https://github.com/rust-lang/crates.io-index" 1341 | dependencies = [ 1342 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1343 | ] 1344 | 1345 | [[package]] 1346 | name = "time" 1347 | version = "0.1.42" 1348 | source = "registry+https://github.com/rust-lang/crates.io-index" 1349 | dependencies = [ 1350 | "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", 1351 | "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", 1352 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1353 | ] 1354 | 1355 | [[package]] 1356 | name = "tokio" 1357 | version = "0.1.18" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | dependencies = [ 1360 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 1361 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1362 | "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", 1363 | "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 1364 | "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 1365 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1366 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1367 | "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 1368 | "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 1369 | "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 1370 | "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "tokio-current-thread" 1375 | version = "0.1.6" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | dependencies = [ 1378 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1379 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1380 | ] 1381 | 1382 | [[package]] 1383 | name = "tokio-executor" 1384 | version = "0.1.7" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | dependencies = [ 1387 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1388 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1389 | ] 1390 | 1391 | [[package]] 1392 | name = "tokio-io" 1393 | version = "0.1.12" 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" 1395 | dependencies = [ 1396 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 1397 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1398 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1399 | ] 1400 | 1401 | [[package]] 1402 | name = "tokio-reactor" 1403 | version = "0.1.9" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | dependencies = [ 1406 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1407 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1408 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1409 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1410 | "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", 1411 | "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 1412 | "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1413 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 1414 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1415 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1416 | "tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "tokio-sync" 1421 | version = "0.1.4" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | dependencies = [ 1424 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1425 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1426 | ] 1427 | 1428 | [[package]] 1429 | name = "tokio-tcp" 1430 | version = "0.1.3" 1431 | source = "registry+https://github.com/rust-lang/crates.io-index" 1432 | dependencies = [ 1433 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 1434 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1435 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1436 | "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", 1437 | "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1438 | "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 1439 | ] 1440 | 1441 | [[package]] 1442 | name = "tokio-threadpool" 1443 | version = "0.1.13" 1444 | source = "registry+https://github.com/rust-lang/crates.io-index" 1445 | dependencies = [ 1446 | "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1447 | "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1448 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1449 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1450 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1451 | "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 1452 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1453 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 1454 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1455 | ] 1456 | 1457 | [[package]] 1458 | name = "tokio-timer" 1459 | version = "0.2.10" 1460 | source = "registry+https://github.com/rust-lang/crates.io-index" 1461 | dependencies = [ 1462 | "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1463 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1464 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 1465 | "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 1466 | ] 1467 | 1468 | [[package]] 1469 | name = "tokio-trace-core" 1470 | version = "0.1.0" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | dependencies = [ 1473 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1474 | ] 1475 | 1476 | [[package]] 1477 | name = "try-lock" 1478 | version = "0.2.2" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | 1481 | [[package]] 1482 | name = "ucd-util" 1483 | version = "0.1.3" 1484 | source = "registry+https://github.com/rust-lang/crates.io-index" 1485 | 1486 | [[package]] 1487 | name = "unicase" 1488 | version = "1.4.2" 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" 1490 | dependencies = [ 1491 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1492 | ] 1493 | 1494 | [[package]] 1495 | name = "unicase" 1496 | version = "2.3.0" 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" 1498 | dependencies = [ 1499 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1500 | ] 1501 | 1502 | [[package]] 1503 | name = "unicode-bidi" 1504 | version = "0.3.4" 1505 | source = "registry+https://github.com/rust-lang/crates.io-index" 1506 | dependencies = [ 1507 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1508 | ] 1509 | 1510 | [[package]] 1511 | name = "unicode-normalization" 1512 | version = "0.1.8" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | dependencies = [ 1515 | "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 1516 | ] 1517 | 1518 | [[package]] 1519 | name = "unicode-width" 1520 | version = "0.1.5" 1521 | source = "registry+https://github.com/rust-lang/crates.io-index" 1522 | 1523 | [[package]] 1524 | name = "unicode-xid" 1525 | version = "0.1.0" 1526 | source = "registry+https://github.com/rust-lang/crates.io-index" 1527 | 1528 | [[package]] 1529 | name = "url" 1530 | version = "1.7.2" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | dependencies = [ 1533 | "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1534 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1535 | "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1536 | ] 1537 | 1538 | [[package]] 1539 | name = "utf8-ranges" 1540 | version = "1.0.2" 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" 1542 | 1543 | [[package]] 1544 | name = "uuid" 1545 | version = "0.7.3" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | dependencies = [ 1548 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1549 | ] 1550 | 1551 | [[package]] 1552 | name = "vcpkg" 1553 | version = "0.2.6" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | 1556 | [[package]] 1557 | name = "vec_map" 1558 | version = "0.8.1" 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" 1560 | 1561 | [[package]] 1562 | name = "version_check" 1563 | version = "0.1.5" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | 1566 | [[package]] 1567 | name = "want" 1568 | version = "0.0.6" 1569 | source = "registry+https://github.com/rust-lang/crates.io-index" 1570 | dependencies = [ 1571 | "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", 1572 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1573 | "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "winapi" 1578 | version = "0.2.8" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | 1581 | [[package]] 1582 | name = "winapi" 1583 | version = "0.3.6" 1584 | source = "registry+https://github.com/rust-lang/crates.io-index" 1585 | dependencies = [ 1586 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1587 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1588 | ] 1589 | 1590 | [[package]] 1591 | name = "winapi-build" 1592 | version = "0.1.1" 1593 | source = "registry+https://github.com/rust-lang/crates.io-index" 1594 | 1595 | [[package]] 1596 | name = "winapi-i686-pc-windows-gnu" 1597 | version = "0.4.0" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | 1600 | [[package]] 1601 | name = "winapi-util" 1602 | version = "0.1.2" 1603 | source = "registry+https://github.com/rust-lang/crates.io-index" 1604 | dependencies = [ 1605 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1606 | ] 1607 | 1608 | [[package]] 1609 | name = "winapi-x86_64-pc-windows-gnu" 1610 | version = "0.4.0" 1611 | source = "registry+https://github.com/rust-lang/crates.io-index" 1612 | 1613 | [[package]] 1614 | name = "wincolor" 1615 | version = "1.0.1" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | dependencies = [ 1618 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1619 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1620 | ] 1621 | 1622 | [[package]] 1623 | name = "ws" 1624 | version = "0.8.0" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | dependencies = [ 1627 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1628 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 1629 | "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 1630 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1631 | "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", 1632 | "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1633 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1634 | "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 1635 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 1636 | "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1637 | ] 1638 | 1639 | [[package]] 1640 | name = "ws2_32-sys" 1641 | version = "0.2.1" 1642 | source = "registry+https://github.com/rust-lang/crates.io-index" 1643 | dependencies = [ 1644 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 1645 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1646 | ] 1647 | 1648 | [[package]] 1649 | name = "yaml-rust" 1650 | version = "0.3.5" 1651 | source = "registry+https://github.com/rust-lang/crates.io-index" 1652 | 1653 | [metadata] 1654 | "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" 1655 | "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" 1656 | "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" 1657 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 1658 | "checksum arc-swap 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4baecaf2f0022852ec4d0582bc4e8d40cccebf29c712c55f094dfa4fcb4ee972" 1659 | "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" 1660 | "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" 1661 | "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" 1662 | "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" 1663 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" 1664 | "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" 1665 | "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" 1666 | "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" 1667 | "checksum bytesize 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "16d794c5fe594cfa8fbe8ae274de4048176c69f2d9ac5e637166e73b71d460b8" 1668 | "checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" 1669 | "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" 1670 | "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" 1671 | "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" 1672 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 1673 | "checksum colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9a455e156a4271e12fd0246238c380b1e223e3736663c7a18ed8b6362028a9" 1674 | "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" 1675 | "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" 1676 | "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" 1677 | "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" 1678 | "checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650" 1679 | "checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" 1680 | "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" 1681 | "checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a" 1682 | "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" 1683 | "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" 1684 | "checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" 1685 | "checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" 1686 | "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" 1687 | "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" 1688 | "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" 1689 | "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" 1690 | "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" 1691 | "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" 1692 | "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" 1693 | "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" 1694 | "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" 1695 | "checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" 1696 | "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 1697 | "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 1698 | "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 1699 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 1700 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 1701 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1702 | "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" 1703 | "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" 1704 | "checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" 1705 | "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" 1706 | "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" 1707 | "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" 1708 | "checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896" 1709 | "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" 1710 | "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" 1711 | "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" 1712 | "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" 1713 | "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" 1714 | "checksum jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" 1715 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 1716 | "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" 1717 | "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" 1718 | "checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" 1719 | "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" 1720 | "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" 1721 | "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" 1722 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1723 | "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" 1724 | "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" 1725 | "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" 1726 | "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" 1727 | "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" 1728 | "checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" 1729 | "checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" 1730 | "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" 1731 | "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" 1732 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 1733 | "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" 1734 | "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 1735 | "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" 1736 | "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" 1737 | "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" 1738 | "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" 1739 | "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" 1740 | "checksum openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)" = "5a0d6b781aac4ac1bd6cafe2a2f0ad8c16ae8e1dd5184822a16c50139f8838d9" 1741 | "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" 1742 | "checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" 1743 | "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" 1744 | "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" 1745 | "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" 1746 | "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" 1747 | "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" 1748 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" 1749 | "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" 1750 | "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" 1751 | "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" 1752 | "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" 1753 | "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" 1754 | "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" 1755 | "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1756 | "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" 1757 | "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" 1758 | "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1759 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1760 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1761 | "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" 1762 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 1763 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 1764 | "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" 1765 | "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" 1766 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 1767 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 1768 | "checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" 1769 | "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" 1770 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 1771 | "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" 1772 | "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 1773 | "checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" 1774 | "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" 1775 | "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 1776 | "checksum reopen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4d219eae473bed7f02c4683e782c268ef50691fd16916fd8b2dc81eccae5ecd7" 1777 | "checksum reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "962fa64e670e70b9d3a81c3688832eb59293ef490e0af5ad169763f62016ac5e" 1778 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1779 | "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" 1780 | "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" 1781 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 1782 | "checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" 1783 | "checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" 1784 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1785 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1786 | "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" 1787 | "checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" 1788 | "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" 1789 | "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" 1790 | "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 1791 | "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" 1792 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1793 | "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" 1794 | "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" 1795 | "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" 1796 | "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" 1797 | "checksum subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "28fc0f40f0c0da73339d347aa7d6d2b90341a95683a47722bc4eebed71ff3c00" 1798 | "checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" 1799 | "checksum sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "11c5f6e8a7a7146f26ffed9a5ff8bab2706f1ac8a413a415e1d211b819d5c24d" 1800 | "checksum systemstat 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "11374381f619810a32d086459e740a0e4a683f15beea3fe5f3cddb40c8791106" 1801 | "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" 1802 | "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" 1803 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" 1804 | "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" 1805 | "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" 1806 | "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 1807 | "checksum tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "65641e515a437b308ab131a82ce3042ff9795bef5d6c5a9be4eb24195c417fd9" 1808 | "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" 1809 | "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" 1810 | "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" 1811 | "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" 1812 | "checksum tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fda385df506bf7546e70872767f71e81640f1f251bdf2fd8eb81a0eaec5fe022" 1813 | "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" 1814 | "checksum tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ec5759cf26cf9659555f36c431b515e3d05f66831741c85b4b5d5dfb9cf1323c" 1815 | "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" 1816 | "checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" 1817 | "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" 1818 | "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" 1819 | "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" 1820 | "checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd" 1821 | "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1822 | "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" 1823 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 1824 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 1825 | "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" 1826 | "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" 1827 | "checksum uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "600ef8213e9f8a0ac1f876e470e90780ae0478eabce7f76aff41b0f4ef0fd5c0" 1828 | "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" 1829 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 1830 | "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 1831 | "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" 1832 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 1833 | "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" 1834 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 1835 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1836 | "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" 1837 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1838 | "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" 1839 | "checksum ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcacc3ba9c1ee43e3fd0846a25489ff22f8906e90775d51b6edbae4b95d71f4" 1840 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 1841 | "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" 1842 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "codechain-agent" 3 | version = "0.1.0" 4 | authors = ["CodeChain Team "] 5 | 6 | [dependencies] 7 | atty = "0.2" 8 | clap = { version = "*", features = ["yaml"] } 9 | colored = "1.6" 10 | crossbeam = "0.4" 11 | env_logger = "0.5.7" 12 | jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" } 13 | libc = "0.2" 14 | log = "0.4.1" 15 | parking_lot = "0.7.1" 16 | reopen = "0.2.2" 17 | reqwest = "0.9.0" 18 | serde = "1.0" 19 | serde_derive = "1.0" 20 | serde_json = "1.0" 21 | subprocess = "0.1.18" 22 | sysinfo = "0.6.1" 23 | systemstat = "0.1.3" 24 | time = "0.1" 25 | ws = "*" 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project is moved to https://github.com/CodeChain-io/codechain-dashboard 2 | 3 | # CodeChain Agent [![Build Status](https://travis-ci.org/CodeChain-io/codechain-agent.svg?branch=master)](https://travis-ci.org/CodeChain-io/codechain-agent) 4 | 5 | ## Requirements 6 | 7 | The following are the software dependencies required to install and run CodeChain-agent: 8 | 9 | - [CodeChain](https://github.com/CodeChain-io/codechain) 10 | - [CodeChain-agent-server](https://github.com/CodeChain-io/codechain-agent-server) 11 | 12 | ### Install dependencies (Ubuntu) 13 | 14 | ``` 15 | sudo apt install pkg-config libssl-dev 16 | ``` 17 | 18 | ## Run 19 | 20 | To run CodeChain-agent, just run 21 | 22 | ``` 23 | cargo run -- --agent-hub-url --codechain-dir --codechain-p2p-address --name 24 | ``` 25 | 26 | ## Formatting 27 | 28 | Make sure you run `rustfmt` before creating a PR to the repo. You need to install the nightly-2018-12-06 version of `rustfmt`. 29 | 30 | ``` 31 | rustup toolchain install nightly-2018-12-06 32 | rustup component add rustfmt-preview --toolchain nightly-2018-12-06 33 | ``` 34 | 35 | To run `rustfmt`, 36 | 37 | ``` 38 | cargo +nightly-2018-12-06 fmt 39 | ``` 40 | 41 | ## User Manual 42 | 43 | Under `docs` folder, run following command. 44 | 45 | ``` 46 | make html 47 | ``` 48 | 49 | User manual will be generated at `docs/_build/html`. 50 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = CodeChainAgentProtocol 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | set SPHINXPROJ=CodeChainAgentProtocol 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'CodeChainAgentProtocol' 23 | copyright = u'2018, Park Juhyung' 24 | author = u'Park Juhyung' 25 | 26 | # The short X.Y version 27 | version = u'' 28 | # The full version, including alpha/beta/rc tags 29 | release = u'' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | ] 43 | 44 | # Add any paths that contain templates here, relative to this directory. 45 | templates_path = ['_templates'] 46 | 47 | # The suffix(es) of source filenames. 48 | # You can specify multiple suffix as a list of string: 49 | # 50 | # source_suffix = ['.rst', '.md'] 51 | source_suffix = '.rst' 52 | 53 | # The master toctree document. 54 | master_doc = 'index' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | # 59 | # This is also used if you do content translation via gettext catalogs. 60 | # Usually you set "language" from the command line for these cases. 61 | language = None 62 | 63 | # List of patterns, relative to source directory, that match files and 64 | # directories to ignore when looking for source files. 65 | # This pattern also affects html_static_path and html_extra_path . 66 | exclude_patterns = [] 67 | 68 | # The name of the Pygments (syntax highlighting) style to use. 69 | pygments_style = 'sphinx' 70 | 71 | 72 | # -- Options for HTML output ------------------------------------------------- 73 | 74 | # The theme to use for HTML and HTML Help pages. See the documentation for 75 | # a list of builtin themes. 76 | # 77 | html_theme = 'alabaster' 78 | 79 | # Theme options are theme-specific and customize the look and feel of a theme 80 | # further. For a list of options available for each theme, see the 81 | # documentation. 82 | # 83 | # html_theme_options = {} 84 | 85 | # Add any paths that contain custom static files (such as style sheets) here, 86 | # relative to this directory. They are copied after the builtin static files, 87 | # so a file named "default.css" will overwrite the builtin "default.css". 88 | html_static_path = ['_static'] 89 | 90 | # Custom sidebar templates, must be a dictionary that maps document names 91 | # to template names. 92 | # 93 | # The default sidebars (for documents that don't match any pattern) are 94 | # defined by theme itself. Builtin themes are using these templates by 95 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 96 | # 'searchbox.html']``. 97 | # 98 | # html_sidebars = {} 99 | 100 | 101 | # -- Options for HTMLHelp output --------------------------------------------- 102 | 103 | # Output file base name for HTML help builder. 104 | htmlhelp_basename = 'CodeChainAgentProtocoldoc' 105 | 106 | 107 | # -- Options for LaTeX output ------------------------------------------------ 108 | 109 | latex_elements = { 110 | # The paper size ('letterpaper' or 'a4paper'). 111 | # 112 | # 'papersize': 'letterpaper', 113 | 114 | # The font size ('10pt', '11pt' or '12pt'). 115 | # 116 | # 'pointsize': '10pt', 117 | 118 | # Additional stuff for the LaTeX preamble. 119 | # 120 | # 'preamble': '', 121 | 122 | # Latex figure (float) alignment 123 | # 124 | # 'figure_align': 'htbp', 125 | } 126 | 127 | # Grouping the document tree into LaTeX files. List of tuples 128 | # (source start file, target name, title, 129 | # author, documentclass [howto, manual, or own class]). 130 | latex_documents = [ 131 | (master_doc, 'CodeChainAgentProtocol.tex', u'CodeChainAgentProtocol Documentation', 132 | u'Park Juhyung', 'manual'), 133 | ] 134 | 135 | 136 | # -- Options for manual page output ------------------------------------------ 137 | 138 | # One entry per manual page. List of tuples 139 | # (source start file, name, description, authors, manual section). 140 | man_pages = [ 141 | (master_doc, 'codechainagentprotocol', u'CodeChainAgentProtocol Documentation', 142 | [author], 1) 143 | ] 144 | 145 | 146 | # -- Options for Texinfo output ---------------------------------------------- 147 | 148 | # Grouping the document tree into Texinfo files. List of tuples 149 | # (source start file, target name, title, author, 150 | # dir menu entry, description, category) 151 | texinfo_documents = [ 152 | (master_doc, 'CodeChainAgentProtocol', u'CodeChainAgentProtocol Documentation', 153 | author, 'CodeChainAgentProtocol', 'One line description of project.', 154 | 'Miscellaneous'), 155 | ] -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | 2 | ========================== 3 | CodeChain Agent Protocol 4 | ========================== 5 | 6 | .. highlight:: typescript 7 | 8 | .. contents:: :local: 9 | 10 | *************** 11 | Term 12 | *************** 13 | 14 | Agent 15 | ===== 16 | 17 | An agent lives in the same machine with a CodeChain node. It queries 18 | CodeChain nodes and get managerial information. It can stop/update/run a 19 | CodeChain program. 20 | 21 | 22 | Agent Hub 23 | ============ 24 | 25 | An agent server queries agents to get information. It saves the collected 26 | data to its own DB. 27 | 28 | 29 | Frontend 30 | ========= 31 | 32 | A frontend provides the visualization of the information collected from agent 33 | servers. 34 | 35 | 36 | *************** 37 | Common 38 | *************** 39 | 40 | JSON RPC 41 | ========= 42 | 43 | This protocol is based on the JSON RPC 2.0 spec 44 | 45 | :: 46 | 47 | --> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1} 48 | <-- {"jsonrpc": "2.0", "result": 19, "id": 1} 49 | 50 | Types 51 | ======= 52 | 53 | .. _type-parcel: 54 | 55 | Parcel 56 | ------- 57 | 58 | :: 59 | 60 | interface Parcel { 61 | // ... 62 | } 63 | 64 | 65 | .. _type-SocketAddr: 66 | 67 | SocketAddr 68 | ------------ 69 | 70 | :: 71 | 72 | type SocketAddr = string // "127.0.0.1:3485" 73 | 74 | .. _type-IpAddr: 75 | 76 | IpAddr 77 | ------ 78 | 79 | :: 80 | 81 | type IpAddr = string // "127.0.0.1" 82 | 83 | .. _type-Block: 84 | 85 | Block 86 | -------- 87 | 88 | :: 89 | 90 | interface Block { 91 | // ... 92 | } 93 | 94 | .. _type-ISO8601: 95 | 96 | ISO8601 97 | ------- 98 | 99 | :: 100 | 101 | type ISO8601 = string // "2018-09-03T23:05:48Z" 102 | 103 | .. _type-ISO8601Duration: 104 | 105 | ISO8601Duration 106 | ----------------- 107 | 108 | :: 109 | 110 | type ISO8601Duration = string // "P1YT30M3S" 111 | 112 | 113 | .. _type-NodeStatus: 114 | 115 | NodeStatus 116 | ---------- 117 | 118 | :: 119 | 120 | type NodeStatus = "Run" | "Stop" | "Error" | "UFO"; 121 | 122 | .. _type-WhiteList 123 | 124 | WhiteList 125 | ---------- 126 | 127 | :: 128 | 129 | type Tag = string; 130 | interface WhiteList = { 131 | list: [IpAddr, Tag][]; 132 | enabled: boolean; 133 | } 134 | 135 | links: type-IpAddr_ 136 | 137 | .. _type-BalckList 138 | 139 | BlackList 140 | ---------- 141 | 142 | :: 143 | 144 | type Tag = string; 145 | interface BlackList = { 146 | list: [IpAddr, Tag][]; 147 | enabled: boolean; 148 | } 149 | 150 | links: type-IpAddr_ 151 | 152 | .. _type-DashboardNodeInfo: 153 | 154 | DashboardNodeInfo 155 | ------------------ 156 | 157 | :: 158 | 159 | interface DashboardNodeInfo { 160 | status: NodeStatus; 161 | name: string; 162 | address?: SocketAddr; 163 | version?: { version: string, hash: string }; 164 | bestBlockId?: { blockNumber: number, hash: H256 }; 165 | name?: string; 166 | } 167 | 168 | links: type-NodeStatus_, type-SocketAddr_ 169 | 170 | .. _type-DashboardUFONodeInfo: 171 | 172 | DashboardUFONodeInfo 173 | -------------------- 174 | 175 | :: 176 | 177 | interface DashboardUFONodeInfo { 178 | status: NodeStatus; 179 | name: string; 180 | address: SocketAddr; 181 | } 182 | 183 | .. _type-NodeInfo: 184 | 185 | NodeInfo 186 | -------- 187 | 188 | :: 189 | 190 | interface NodeInfo { 191 | status: NodeStatus; 192 | name: string; 193 | agentVersion: String; 194 | address?: SocketAddr; 195 | startOptions?: { env: string, args: string }; 196 | version?: { version: string, hash: string }; 197 | bestBlockId?: { blockNumber: number, hash: H256 }; 198 | pendingParcels: Parcel[]; 199 | peers: SocketAddr[]; 200 | whitelist?: WhiteList; 201 | blacklist?: BlackList; 202 | hardware: { 203 | cpuUsage: number[], 204 | diskUsage: { total: i64, available: i64, percentageUsed: f64}, 205 | memoryUsage: { total: i64, available: i64, percentageUsed: f64} 206 | }; 207 | // events from this node order by created time. 208 | events: Event[]; 209 | } 210 | 211 | links: type-NodeStatus_, type-SocketAddr_, type-Parcel_, type-WhiteList_, type-BlackList_ 212 | 213 | .. _type-UFONodeInfo: 214 | 215 | UFONodeInfo 216 | ----------- 217 | 218 | :: 219 | 220 | interface UFONodeInfo { 221 | name: string; 222 | address: SocketAddr; 223 | status: NodeStatus; 224 | } 225 | 226 | Error 227 | ======= 228 | 229 | JSON RPC error space 230 | ----------------------- 231 | 232 | JSON RPC uses -32768 to -32000 as reserved pre-defined errors. 233 | 234 | :: 235 | 236 | namespace PredefinedErrors { 237 | const ParseError: number = -32700; 238 | const InvalidRequest: number = -32600; 239 | const MethodNotFound: number = -32601; 240 | const InvalidParams: number = -32602; 241 | const InternalError: number = -32603; 242 | const serverErrorStart: number = -32099; 243 | const serverErrorEnd: number = -32000; 244 | const ServerNotInitialized: number = -32002; 245 | const UnknownErrorCode: number = -32001; 246 | } 247 | 248 | .. _common-error: 249 | 250 | Common error space 251 | -------------------- 252 | 253 | -9999 ~ 0 are reserved for common error codes. 254 | 255 | :: 256 | 257 | namespace CommonErrors { 258 | const CodeChainIsNotRunning = 0; 259 | const AgentNotFound = -1; 260 | } 261 | 262 | 263 | Protocol error space 264 | ----------------------- 265 | 266 | Easy protocol use -19999 ~ 10000 numbers as error code. 267 | These error codes has different meaning according to which protocol returns. 268 | 269 | 270 | ********************** 271 | Agent Hub -> Agent 272 | ********************** 273 | 274 | Requests 275 | ========= 276 | 277 | codechain_callRPC ➡️ ⬅️ 278 | ------------------------ 279 | 280 | Run codechain RPC through agent. JSONRPC result will be included in innerResponse field. 281 | 282 | .. _type-CodeChainCallRPCRequest: 283 | 284 | Request 285 | """"""""" 286 | 287 | :: 288 | 289 | type CodeChainCallRPCRequest = [ 290 | string, // RPC's name 291 | any[] // RPC's arguments 292 | ]; 293 | 294 | .. _type-CodeChainCallRPCResponse: 295 | 296 | Response 297 | """""""""" 298 | 299 | :: 300 | 301 | interface CodeChainCallRPCResponse { 302 | innerResponse: any; 303 | } 304 | 305 | Error 306 | """"""" 307 | 308 | :: 309 | 310 | interface CodeChainCallRPCErrors { 311 | /** 312 | * Some network error occured while sending RPC to CodeChain 313 | */ 314 | const NetworkError = -10001 315 | } 316 | 317 | hardware_get ➡️ ⬅️ 318 | ------------------ 319 | 320 | Get hardware information of the computer which the CodeChain and agent lives. 321 | 322 | Request 323 | """""""" 324 | 325 | No request arguments 326 | 327 | Response 328 | """"""""" 329 | 330 | :: 331 | 332 | interface HardwareGetResponse { 333 | cpuUsage: number[]; 334 | diskUsage: { total: i64, available: i64, percentageUsed: f64}; 335 | memoryUsage: { total: i64, available: i64, percentageUsed: f64}; 336 | } 337 | 338 | agent_getInfo ➡️ ⬅️ 339 | ------------------ 340 | 341 | Get agent's status and CodeChain's address 342 | 343 | Request 344 | """""""" 345 | 346 | No request arguments 347 | 348 | Response 349 | """"""""" 350 | 351 | :: 352 | 353 | interface AgentGetInfoResponse { 354 | status: NodeStatus; 355 | name: string; 356 | address?: SocketAddr; 357 | codechainCommitHash: String; 358 | } 359 | 360 | links: type-NodeStatus_, type-SocketAddr_ 361 | 362 | shell_startCodeChain ➡️ ⬅️ 363 | -------------------------- 364 | 365 | .. _type-ShellStartCodeChainRequest: 366 | 367 | Request 368 | """""""" 369 | 370 | :: 371 | 372 | type ShellStartCodeChainRequest = [ 373 | { 374 | env: string; // "RUST_LOG=trace" 375 | args: string; // "-c husky" 376 | } 377 | ] 378 | 379 | Response 380 | """"""""" 381 | 382 | ``()`` 383 | 384 | 385 | Error 386 | """"""" 387 | 388 | :: 389 | 390 | namespace ShellStartCodeChainErrors { 391 | /** 392 | * There is a codechain instance already running. 393 | */ 394 | const AlreadyRunning = -10001; 395 | /** 396 | * The format of given `env` is wrong. 397 | */ 398 | const EnvParseError = -10002; 399 | } 400 | 401 | 402 | shell_stopCodeChain ➡️ ⬅️ 403 | -------------------------- 404 | 405 | Stop running codechain. 406 | 407 | Request 408 | """"""""" 409 | 410 | No request arguments 411 | 412 | Response 413 | """"""""" 414 | 415 | ``()`` 416 | 417 | Error 418 | """""" 419 | 420 | Could return ``CodeChainIsNotRunning`` 421 | 422 | links: common-error_ 423 | 424 | 425 | shell_getUptime ➡️ ⬅️ 426 | --------------------- 427 | 428 | Get codechain's uptime. If codechain is not running now, it returns null. 429 | 430 | Request 431 | """"""""" 432 | 433 | No request arguments 434 | 435 | Response 436 | """"""""" 437 | 438 | :: 439 | 440 | type ShellGetUptime = ISO8601Duration | null 441 | 442 | links: type-ISO8601Duration_ 443 | 444 | shell_getCodeChainLog ➡️ ⬅️ 445 | ---------------------------- 446 | 447 | Get CodeChain's logs. 448 | 449 | Request 450 | """"""""" 451 | 452 | :: 453 | type ShellGetCodeChainRequest = [ 454 | { 455 | levels: string[]; // ex) ["info", "warn", "error] 456 | } 457 | ] 458 | 459 | Response 460 | """"""""" 461 | 462 | :: 463 | 464 | type ShellGetCodeChainResponse = LogGetResponse 465 | 466 | links: type-LogGetResponse_ 467 | 468 | shell_updateCodeChain ➡️ ⬅️ 469 | --------------------------- 470 | 471 | Update CodeChain source code to the given commit hash. 472 | 473 | .. _type-UpdateCodeChainRequest: 474 | 475 | Request 476 | """"""""" 477 | 478 | Commit hash of the CodeChain repository 479 | 480 | :: 481 | 482 | type UpdateCodeChainRequest = [{ 483 | env: string; 484 | args: string; 485 | }, { 486 | type: "git" | "binary" 487 | commitHash?: string; 488 | binaryURL?: string; 489 | binaryChecksum?: string; 490 | }] 491 | 492 | Response 493 | """"""""" 494 | 495 | ``()`` 496 | 497 | Error 498 | """"""" 499 | 500 | :: 501 | 502 | namespace ShellUpdateCodeChainErrors { 503 | /** 504 | * Cannot find the given commit hash from the repository 505 | */ 506 | const NoSuchCommitHash = -10001 507 | } 508 | 509 | ********************** 510 | Agent -> Agent Hub 511 | ********************** 512 | 513 | Notification 514 | =============== 515 | 516 | event_connected ➡️ 517 | ------------------- 518 | 519 | This event fires when a node is connected to another node. 520 | 521 | Arguments 522 | """"""""" 523 | 524 | Argument is the other node's name. 525 | ``string`` 526 | 527 | 528 | event_disconnected ➡️ 529 | --------------------- 530 | 531 | This event fires when a node is disconnected from another node. 532 | 533 | Arguments 534 | """"""""" 535 | 536 | Argument is the other node's name. 537 | ``string`` 538 | 539 | 540 | event_parcelSent ➡️ 541 | ------------------- 542 | 543 | This event fires when a node propagate parcels to another node. 544 | 545 | Arguments 546 | """""""""" 547 | 548 | First argument is the node's name which received the parcels. 549 | Second argument is the content of the parcels. 550 | 551 | ``[string, Parcel[]]`` 552 | 553 | links: type-Parcel_ 554 | 555 | 556 | event_parcelReceived ➡️ 557 | ------------------------- 558 | 559 | This event fires when a node receives parcels from another node. 560 | 561 | Arguments 562 | """"""""" 563 | 564 | First argument is the node's name which sent a parcel. 565 | 566 | ``[string, Parcel[]]`` 567 | 568 | links: type-Parcel_ 569 | 570 | 571 | event_parcelRecevedByRPC ➡️ 572 | ----------------------------- 573 | 574 | This event fires when a node receives a parcel by `chain_sendSignedParcel` RPC. 575 | 576 | Arguments 577 | """"""""" 578 | 579 | ``[Parcel]`` 580 | 581 | links: type-Parcel_ 582 | 583 | event_blockSent ➡️ 584 | ------------------- 585 | 586 | This event fires when a node sent a block to another node. 587 | 588 | Arguments 589 | """"""""" 590 | 591 | The first argument is the node's name which received a block. 592 | 593 | ``[string, Block]`` 594 | 595 | links: type-SocketAddr_, type-Block_ 596 | 597 | 598 | event_blockRequested ➡️ 599 | ------------------------ 600 | 601 | This event fires when a node requests a block to another node. 602 | 603 | Arguments 604 | """"""""" 605 | 606 | The first argument is the node's name which received 'block request'. 607 | 608 | ``[string, Block]`` 609 | 610 | links: type-SocketAddr_, type-Block_ 611 | 612 | 613 | event_blockReceived ➡️ 614 | ------------------------ 615 | 616 | This event fires when a node received a block from another node. 617 | 618 | Arguments 619 | """"""""" 620 | 621 | The first argument is the name of a node which sent a block. 622 | 623 | ``[string, Block]`` 624 | 625 | links: type-SocketAddr_, type-Block_ 626 | 627 | 628 | event_miningStarted ➡️ 629 | ----------------------- 630 | 631 | This event fires when a node starts mining. 632 | 633 | Arguments 634 | """"""""" 635 | 636 | First argument is the block which is will be mined. 637 | Second argument is the target score. 638 | 639 | ``[Block, number]`` 640 | 641 | 642 | event_miningSucceeded ➡️ 643 | ------------------------ 644 | 645 | This event fires when a node succeed mining. 646 | 647 | Arguments 648 | """"""""" 649 | 650 | First argument is the block which is will be mined. 651 | Second argument is the target score. 652 | ``[Block, targetScore]`` 653 | 654 | 655 | ************************** 656 | Frontend <-> Agent Hub 657 | ************************** 658 | 659 | Dashboard Page 660 | ============== 661 | 662 | dashboard_getNetwork ➡️ ⬅️ 663 | -------------------------- 664 | 665 | Frontend requests information to agent server to render dashboard page. 666 | 667 | Request 668 | """"""""" 669 | 670 | No request arguments 671 | 672 | Response 673 | """"""""" 674 | 675 | :: 676 | 677 | interface DashboardGetNetworkResponse { 678 | nodes: (DashboardNodeInfo | DashboardUFONodeInfo)[]; 679 | connections: { nodeA: string; nodeB: string; }[] // nodeA and nodeB is the name of the nodes. 680 | } 681 | 682 | links: type-DashboardNodeInfo_, type-DashboardUFONodeInfo_ 683 | 684 | dashboard_updated ➡️ 685 | -------------------- 686 | 687 | Arguments 688 | """""""""" 689 | :: 690 | 691 | type DashboardUpdatedArguments = [{ 692 | nodes?: ({ address: SocketAddr; } | Partial | Partial)[]; 693 | connectionsAdded?: { nodeA: string; nodeB: string; }[] 694 | connectionsRemoved?: { nodeA: string; nodeB: string; }[] 695 | }] 696 | 697 | links: type-DashboardNodeInfo_, type-DashboardUFONodeInfo_ 698 | 699 | Node Page 700 | ========== 701 | 702 | node_getInfo ➡️ ⬅️ 703 | ------------------ 704 | 705 | Frontend requests information to agent server to render node page. 706 | 707 | Request 708 | """"""""" 709 | 710 | First argument is the name of a node. 711 | 712 | ``[string]`` 713 | 714 | Response 715 | """"""""" 716 | 717 | :: 718 | 719 | type NodeGetInfoResponse = NodeInfo | UFONodeInfo 720 | 721 | links: type-NodeInfo_, type-UFONodeInfo_ 722 | 723 | node_updated ➡️ 724 | ---------------- 725 | 726 | Arguments 727 | """"""""" 728 | 729 | :: 730 | 731 | type NodeUpdatedArguments = [{ 732 | name: string; 733 | address?: SocketAddr; 734 | status?: NodeStatus; 735 | version?: { version: string, hash: string }; 736 | bestBlockId?: { blockNumber: number, hash: H256 }; 737 | pendingParcels?: Parcel[]; 738 | peers?: SocketAddr[]; 739 | whitelist?: WhiteList; 740 | blacklist?: BlackList; 741 | hardware?: HardwareGetResponse; 742 | eventsAdded?: Event[]; 743 | }] 744 | 745 | links: type-NodeStatus_, type-HardwareGetResponse_, type-WhiteList_, type-BlackList_ 746 | 747 | node_start ➡️ ⬅️ 748 | ---------------- 749 | 750 | Request 751 | """"""""" 752 | 753 | First argument is the name of the node. 754 | 755 | :: 756 | 757 | type NodeStartRequest = [ 758 | string, 759 | { 760 | env: string; // "RUST_LOG=trace" 761 | args: string; // "-c husky" 762 | } 763 | ] 764 | 765 | links: type-ShellStartCodeChainRequest_ 766 | 767 | Response 768 | """"""""" 769 | 770 | ``()`` 771 | 772 | Error 773 | """"""" 774 | 775 | :: 776 | 777 | namespace NodeStartErrors { 778 | /** 779 | * There is a codechain instance already running. 780 | */ 781 | const AlreadyRunning = -10001; 782 | /** 783 | * The format of given `env` is wrong. 784 | */ 785 | const EnvParseError = -10002; 786 | } 787 | 788 | 789 | node_stop ➡️ ⬅️ 790 | --------------- 791 | 792 | Request 793 | """"""""" 794 | 795 | First argument is the name of the node. 796 | 797 | :: 798 | 799 | type NodeStopRequest = [string] 800 | 801 | 802 | Response 803 | """"""""" 804 | 805 | ``()`` 806 | 807 | Error 808 | """""" 809 | 810 | Could return ``CodeChainIsNotRunning`` 811 | 812 | links: common-error_ 813 | 814 | node_update ➡️ ⬅️ 815 | ----------------- 816 | 817 | Request 818 | """"""""" 819 | 820 | First argument is the name of the node. 821 | 822 | :: 823 | 824 | type NodeUpdateRequest = [ 825 | string, // The name of the node 826 | UpdateCodeChainRequest[1] 827 | ] 828 | 829 | links: type-UpdateCodeChainRequest_ 830 | 831 | Response 832 | """"""""" 833 | 834 | ``()`` 835 | 836 | Error 837 | """""" 838 | 839 | :: 840 | 841 | namespace NodeUpdateErrors { 842 | /** 843 | * Cannot find the given commit hash from the repository 844 | */ 845 | const NoSuchCommitHash = -10001 846 | } 847 | 848 | 849 | RPC Page 850 | ======== 851 | 852 | rpc_getHistory ➡️ ⬅️ 853 | -------------------- 854 | 855 | Request 856 | """"""""" 857 | 858 | :: 859 | 860 | interface RPCGetHistoryRequest { 861 | from: number; 862 | count: number; 863 | } 864 | 865 | Response 866 | """"""""" 867 | 868 | :: 869 | 870 | interface RPCGetHistoryResponse { 871 | histories: { 872 | RPCArguments: string[]; 873 | RPCResponse: string; 874 | sentTime: ISO8601; 875 | }[] 876 | } 877 | 878 | links: type-ISO8601_ 879 | 880 | rpc_run ➡️ ⬅️ 881 | -------------- 882 | 883 | Request 884 | """"""""" 885 | 886 | :: 887 | 888 | type RPCRunRequest = CodeChainCallRPCRequest 889 | 890 | links: type-CodeChainCallRPCRequest_ 891 | 892 | Response 893 | """"""""" 894 | 895 | :: 896 | 897 | type RPCRunResponse = CodeChainCallRPCResponse 898 | 899 | links: type-CodeChainCallRPCResponse_ 900 | 901 | 902 | 903 | Log Page 904 | ======== 905 | 906 | log_getTargets ➡️ ⬅️ 907 | -------------------- 908 | 909 | Get targets of log data. The Agent Hub get targets from DB and sends them to the Dashboard. 910 | 911 | Request 912 | """"""""" 913 | 914 | No request arguments 915 | 916 | Response 917 | """"""""" 918 | 919 | :: 920 | 921 | interface LogGetTargetsResponse { 922 | targets: string[]; 923 | } 924 | 925 | 926 | log_get ➡️ ⬅️ 927 | -------------------- 928 | 929 | Get logs with query parameter. 930 | 931 | Request 932 | """"""""" 933 | 934 | :: 935 | 936 | type LogGetRequest = [ 937 | { 938 | // If you do not want to filter logs, omit "filter" field. 939 | filter?: { 940 | nodeNames: string[]; 941 | levels: ("error" | "warn" | "info" | "debug" | "trace")[]; 942 | targets: string[]; 943 | }; 944 | // If "search" field is ommited or empty, log is not filtered by keyword. 945 | search?: string; 946 | // If "time" field is ommitted, all log will be returned. 947 | time?: { 948 | fromTime: ISO8601; 949 | toTime: ISO8601; 950 | }; 951 | // Page starts from 1. If ommitted, default value is 1. 952 | page?: number; 953 | // If ommitted, default value is 100. 954 | itemPerPage?: number; 955 | // If ommitted, default value is "ASC". 956 | orderBy?: "ASC" | "DESC"; 957 | } 958 | ] 959 | 960 | links: type-ISO8601_ 961 | 962 | Response 963 | """"""""" 964 | 965 | :: 966 | 967 | interface LogGetResponse = { 968 | logs: { 969 | id: string; 970 | nodeName: string; 971 | level: string; 972 | target: string; 973 | timestamp: ISO8601; 974 | message: string; 975 | }[] 976 | } 977 | 978 | .. _type-LogGetResponse: 979 | links: type-ISO8601_ 980 | 981 | .. 982 | rpc_name 983 | ----------- 984 | 985 | Request 986 | """"""""" 987 | 988 | :: 989 | 990 | x 991 | 992 | Response 993 | """"""""" 994 | 995 | :: 996 | 997 | x 998 | 999 | rpc_name 1000 | ----------- 1001 | 1002 | Arguments 1003 | """"""""" 1004 | 1005 | ``[]`` 1006 | 1007 | ********************** 1008 | Agent Hub web 1009 | ********************** 1010 | 1011 | Agent server serve codechain's log file using HTTP. 1012 | 1013 | Someone could get Agent(127.0.0.1:3485)'s logfile using ``curl http://agenthub.com:5012/log/127.0.0.1:3485`` 1014 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | 1.32.0 2 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | indent_style = "Block" 2 | use_small_heuristics = "Off" # "Default" 3 | binop_separator = "Front" 4 | # combine_control_expr = true 5 | comment_width = 120 # 80 6 | condense_wildcard_suffixes = true # false 7 | control_brace_style = "AlwaysSameLine" 8 | # disable_all_formatting = false 9 | error_on_line_overflow = false # true 10 | # error_on_unformatted = false 11 | fn_args_density = "Tall" 12 | brace_style = "PreferSameLine" # "SameLineWhere" 13 | empty_item_single_line = true 14 | fn_single_line = false 15 | # where_single_line = false 16 | force_explicit_abi = true 17 | format_strings = false 18 | hard_tabs = false 19 | imports_indent = "Block" # "Visual" 20 | imports_layout = "Mixed" 21 | merge_imports = false 22 | match_block_trailing_comma = false 23 | max_width = 120 # 100 24 | merge_derives = true 25 | # force_multiline_blocks = false 26 | newline_style = "Unix" 27 | normalize_comments = false 28 | remove_nested_parens = true 29 | reorder_imports = true 30 | reorder_modules = true 31 | # reorder_impl_items = false 32 | # report_todo = "Never" 33 | # report_fixme = "Never" 34 | # skip_children = false 35 | space_after_colon = true 36 | space_before_colon = false 37 | struct_field_align_threshold = 0 38 | spaces_around_ranges = false 39 | ## struct_lit_single_line = true 40 | tab_spaces = 4 41 | trailing_comma = "Vertical" 42 | trailing_semicolon = false # true 43 | # type_punctuation_density = "Wide" 44 | use_field_init_shorthand = true # false 45 | use_try_shorthand = true # false 46 | wrap_comments = false 47 | match_arm_blocks = true 48 | blank_lines_upper_bound = 2 # 1 49 | blank_lines_lower_bound = 0 50 | hide_parse_errors = false 51 | color = "Always" # "Auto" 52 | unstable_features = false 53 | # license_template_path 54 | -------------------------------------------------------------------------------- /src/agent.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | use std::rc::Rc; 3 | use std::sync::Arc; 4 | use std::thread; 5 | use std::time::Duration; 6 | 7 | use ws::connect; 8 | 9 | use super::handler::WebSocketHandler; 10 | use super::hardware_usage::HardwareService; 11 | use super::logger::init as logger_init; 12 | use super::process::{self, ProcessOption}; 13 | use super::rpc::api::add_routing; 14 | use super::rpc::router::Router; 15 | use super::types::{AgentArgs, HandlerContext}; 16 | 17 | pub fn run(args: &AgentArgs) { 18 | logger_init().expect("Logger should be initialized"); 19 | 20 | let count = Rc::new(Cell::new(0)); 21 | 22 | let mut router = Arc::new(Router::new()); 23 | add_routing(Arc::get_mut(&mut router).unwrap()); 24 | 25 | let process = process::spawn(ProcessOption { 26 | codechain_dir: args.codechain_dir.to_string(), 27 | log_file_path: args.log_file_path.to_string(), 28 | }); 29 | 30 | let hardware_service = HardwareService::run_thread(); 31 | 32 | let context = Arc::new(HandlerContext { 33 | codechain_address: args.codechain_address, 34 | name: args.name.to_string(), 35 | process: process.clone(), 36 | hardware_service: hardware_service.clone(), 37 | }); 38 | 39 | loop { 40 | let count = count.clone(); 41 | let router = router.clone(); 42 | let context = context.clone(); 43 | cinfo!(MAIN, "Connect to {}", args.hub_url); 44 | if let Err(err) = connect(args.hub_url, move |out| WebSocketHandler { 45 | out, 46 | count: count.clone(), 47 | router: router.clone(), 48 | context: context.clone(), 49 | }) { 50 | cerror!(MAIN, "Error from websocket {}", err); 51 | } 52 | cinfo!(MAIN, "Unconnected from Hub"); 53 | thread::sleep(Duration::new(1, 0)); 54 | } 55 | 56 | // cinfo!(MAIN, "Close CodeChain"); 57 | // let (tx, rx) = channel(); 58 | // if let Err(err) = process.send(ProcessMessage::Quit { 59 | // callback: tx, 60 | // }) { 61 | // cerror!(MAIN, "Error while closing CodeChain {}", err); 62 | // return 63 | // } 64 | // match rx.recv() { 65 | // Err(err) => cerror!(MAIN, "Error while closing CodeChain {}", err), 66 | // Ok(Err(err)) => cerror!(MAIN, "Error while closing CodeChain {:?}", err), 67 | // Ok(_) => {} 68 | // } 69 | // 70 | // hardware_service.quit(); 71 | } 72 | -------------------------------------------------------------------------------- /src/agent.yml: -------------------------------------------------------------------------------- 1 | name: cagent 2 | version: "0.1.0" 3 | version_short: "v" 4 | author: CodeChain Team 5 | about: CodeChain Agent 6 | args: 7 | - codechain-dir: 8 | long: codechain-dir 9 | help: CodeChain's repository 10 | required: true 11 | takes_value: true 12 | - log-file: 13 | long: log-file 14 | help: log file will be saved to the path 15 | required: false 16 | takes_value: true 17 | - agent-hub-url: 18 | long: agent-hub-url 19 | help: URL of Agent Hub. ex) "ws://127.0.0.1:4012" 20 | required: true 21 | takes_value: true 22 | - codechain-p2p-address: 23 | long: codechain-p2p-address 24 | short: a 25 | help: Codechain node's p2p address. ex) "127.0.0.1" 26 | required: true 27 | takes_value: true 28 | - name: 29 | long: name 30 | short: n 31 | help: Agent's name. This will be present in the Dashboard. 32 | required: true 33 | takes_value: true 34 | -------------------------------------------------------------------------------- /src/handler.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | use std::rc::Rc; 3 | use std::sync::Arc; 4 | 5 | use jsonrpc_core::types::{ 6 | Call, Error as JSONRPCError, ErrorCode, Failure, Id, MethodCall, Response, Success, Version, 7 | }; 8 | use serde_json; 9 | use ws::{CloseCode, Error as WSError, Handler, Handshake, Message, Result, Sender}; 10 | 11 | use super::rpc::router::{Error as RouterError, Router}; 12 | use super::types::HandlerContext; 13 | 14 | pub struct WebSocketHandler { 15 | pub out: Sender, 16 | pub count: Rc>, 17 | pub router: Arc, 18 | pub context: Arc, 19 | } 20 | 21 | impl Handler for WebSocketHandler { 22 | fn on_open(&mut self, _: Handshake) -> Result<()> { 23 | // We have a new connection, so we increment the connection counter 24 | self.count.set(self.count.get() + 1); 25 | Ok(()) 26 | } 27 | 28 | fn on_message(&mut self, msg: Message) -> Result<()> { 29 | ctrace!(WEB, "Received {}", msg); 30 | 31 | let response: Option = match msg { 32 | Message::Text(text) => { 33 | let deserialized = serde_json::from_str(&text); 34 | match deserialized { 35 | Err(_) => Some( 36 | Failure { 37 | jsonrpc: Some(Version::V2), 38 | id: Id::Null, 39 | error: JSONRPCError::new(ErrorCode::ParseError), 40 | } 41 | .into(), 42 | ), 43 | Ok(Call::Invalid(id)) => Some( 44 | Failure { 45 | jsonrpc: Some(Version::V2), 46 | id, 47 | error: JSONRPCError::new(ErrorCode::ParseError), 48 | } 49 | .into(), 50 | ), 51 | Ok(Call::MethodCall(MethodCall { 52 | id, 53 | method, 54 | params, 55 | .. 56 | })) => { 57 | let value_params = serde_json::to_value(params).expect("Change to value always success"); 58 | match self.router.run(self.context.as_ref(), &method, value_params) { 59 | Ok(Some(value)) => Some( 60 | Success { 61 | jsonrpc: Some(Version::V2), 62 | result: value, 63 | id, 64 | } 65 | .into(), 66 | ), 67 | Ok(None) => { 68 | let mut error = JSONRPCError::new(ErrorCode::InternalError); 69 | error.data = Some(serde_json::Value::String("API returns no value".to_string())); 70 | Some( 71 | Failure { 72 | jsonrpc: Some(Version::V2), 73 | id, 74 | error, 75 | } 76 | .into(), 77 | ) 78 | } 79 | Err(RouterError::MethodNotFound) => Some( 80 | Failure { 81 | jsonrpc: Some(Version::V2), 82 | id, 83 | error: JSONRPCError::new(ErrorCode::MethodNotFound), 84 | } 85 | .into(), 86 | ), 87 | Err(RouterError::RPC(err)) => Some( 88 | Failure { 89 | jsonrpc: Some(Version::V2), 90 | id, 91 | error: err.to_jsonrpc_error(), 92 | } 93 | .into(), 94 | ), 95 | } 96 | } 97 | Ok(Call::Notification(_)) => None, 98 | } 99 | } 100 | _ => Some( 101 | Failure { 102 | jsonrpc: Some(Version::V2), 103 | id: Id::Null, 104 | error: JSONRPCError::new(ErrorCode::ServerError(3)), 105 | } 106 | .into(), 107 | ), 108 | }; 109 | 110 | if let Some(response) = response { 111 | let serialized = serde_json::to_string(&response).unwrap(); 112 | ctrace!(WEB, "Reply to the Agent Hub {}", serialized); 113 | self.out.send(Message::Text(serialized)) 114 | } else { 115 | Ok(()) 116 | } 117 | } 118 | 119 | fn on_close(&mut self, code: CloseCode, reason: &str) { 120 | match code { 121 | CloseCode::Normal => cinfo!(WEB, "The client is done with the connection."), 122 | CloseCode::Away => cinfo!(WEB, "The client is leaving the site."), 123 | CloseCode::Abnormal => { 124 | cinfo!(WEB, "Closing handshake failed! Unable to obtain closing status from client.") 125 | } 126 | _ => cinfo!(WEB, "The client encountered an error: {}", reason), 127 | } 128 | 129 | // The connection is going down, so we need to decrement the count 130 | self.count.set(self.count.get() - 1) 131 | } 132 | 133 | fn on_error(&mut self, err: WSError) { 134 | if let Err(error) = self.out.close_with_reason(CloseCode::Error, "Error") { 135 | cerror!(WEB, "Fail to close connection {}", error); 136 | } 137 | cerror!(WEB, "The server encountered an error: {:?}", err); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/hardware_usage.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::sync::Arc; 3 | use std::thread; 4 | use std::time::Duration; 5 | 6 | use crossbeam::channel; 7 | use crossbeam::channel::{Receiver, Sender}; 8 | use parking_lot::Mutex; 9 | use sysinfo; 10 | use sysinfo::{DiskExt, SystemExt}; 11 | use systemstat; 12 | use systemstat::{CPULoad, DelayedMeasurement, Platform}; 13 | 14 | /** 15 | * We use both sysinfo and systemstat 16 | * sysinfo is slow on single core machine when calculating cpu usage. 17 | * But sysinfo gives disk usage by disk(not by mount) 18 | * 19 | * systemstat is fast when calculating cpu usage. 20 | * 21 | * cpu : systemstat 22 | * memory : systemstat 23 | * disk : sysinfo 24 | */ 25 | 26 | #[derive(Clone)] 27 | pub struct HardwareService { 28 | quit: Sender<()>, 29 | hardware_info: Arc>, 30 | } 31 | 32 | type CpuMeasurement = DelayedMeasurement>; 33 | 34 | impl HardwareService { 35 | pub fn create() -> (Self, Receiver<()>) { 36 | let (tx, rx) = channel::unbounded(); 37 | ( 38 | Self { 39 | quit: tx, 40 | hardware_info: Arc::new(Mutex::new(HardwareInfo::default())), 41 | }, 42 | rx, 43 | ) 44 | } 45 | 46 | pub fn run_thread() -> HardwareService { 47 | let (mut hardware_service, quit_rx) = HardwareService::create(); 48 | let hardware_service_ret = hardware_service.clone(); 49 | 50 | thread::Builder::new() 51 | .name("hardware".to_string()) 52 | .spawn(move || { 53 | let mut sysinfo_sys = sysinfo::System::new(); 54 | 55 | loop { 56 | let measurement = match hardware_service.prepare_cpu_usage() { 57 | Ok(measurement) => Some(measurement), 58 | Err(_) => { 59 | // Do not print error. 60 | // There will be too many error if cpu usage is not supported 61 | None 62 | } 63 | }; 64 | 65 | let timeout = Duration::new(1, 0); 66 | select! { 67 | recv(quit_rx, _msg) => { 68 | cinfo!(HARDWARE, "Close hardware thread"); 69 | return 70 | }, 71 | recv(channel::after(timeout)) => {} 72 | } 73 | 74 | let _ = hardware_service.update(measurement, &mut sysinfo_sys); 75 | // Do not print error. 76 | // There will be too many error if cpu usage is not supported 77 | } 78 | }) 79 | .expect("Should success running process thread"); 80 | 81 | hardware_service_ret 82 | } 83 | 84 | fn prepare_cpu_usage(&self) -> Result { 85 | let sys = systemstat::System::new(); 86 | Ok(sys.cpu_load().map_err(|err| err.description().to_string())?) 87 | } 88 | 89 | fn update(&mut self, cpu_measure: Option, sysinfo_sys: &mut sysinfo::System) -> Result<(), String> { 90 | let cpu_usage = if let Some(measure) = cpu_measure { 91 | let cpu = measure.done().map_err(|err| err.description().to_string())?; 92 | cpu.iter().map(|core| f64::from(core.user + core.system)).collect() 93 | } else { 94 | Vec::new() 95 | }; 96 | 97 | let disk_usage = get_disk_usage(sysinfo_sys); 98 | let mut systemstat_sys = systemstat::System::new(); 99 | let memory_usage = get_memory_usage(&mut systemstat_sys); 100 | 101 | if let Some(mut hardware_info) = self.hardware_info.try_lock() { 102 | *hardware_info = HardwareInfo { 103 | cpu_usage, 104 | disk_usage, 105 | memory_usage, 106 | }; 107 | } else { 108 | cdebug!(HARDWARE, "Cannot acquire hardware_info lock"); 109 | } 110 | Ok(()) 111 | } 112 | 113 | pub fn get(&self) -> HardwareInfo { 114 | if let Some(hardware_info) = self.hardware_info.try_lock() { 115 | hardware_info.clone() 116 | } else { 117 | Default::default() 118 | } 119 | } 120 | 121 | #[allow(dead_code)] 122 | pub fn quit(&self) { 123 | self.quit.send(()); 124 | } 125 | } 126 | 127 | #[derive(Debug, Serialize, Default, Clone)] 128 | #[serde(rename_all = "camelCase")] 129 | pub struct HardwareUsage { 130 | pub total: i64, 131 | pub available: i64, 132 | pub percentage_used: f64, 133 | } 134 | 135 | #[derive(Debug, Serialize, Default, Clone)] 136 | #[serde(rename_all = "camelCase")] 137 | pub struct HardwareInfo { 138 | pub cpu_usage: Vec, 139 | pub disk_usage: HardwareUsage, 140 | pub memory_usage: HardwareUsage, 141 | } 142 | 143 | fn get_disk_usage(sys: &mut sysinfo::System) -> HardwareUsage { 144 | sys.refresh_disk_list(); 145 | sys.refresh_disks(); 146 | 147 | let mut total: i64 = 0; 148 | let mut available: i64 = 0; 149 | for disk in sys.get_disks() { 150 | total += disk.get_total_space() as i64; 151 | available += disk.get_available_space() as i64; 152 | } 153 | let percentage_used = if total == 0 { 154 | 0f64 155 | } else { 156 | (total - available) as f64 / total as f64 157 | }; 158 | HardwareUsage { 159 | total, 160 | available, 161 | percentage_used, 162 | } 163 | } 164 | 165 | fn get_memory_usage(sys: &mut systemstat::System) -> HardwareUsage { 166 | let mem = match sys.memory() { 167 | Ok(mem) => mem, 168 | Err(_) => return HardwareUsage::default(), 169 | }; 170 | 171 | let total = mem.total.as_usize() as i64; 172 | let available = mem.free.as_usize() as i64; 173 | let used = total - available; 174 | let percentage_used = if total == 0 { 175 | 0f64 176 | } else { 177 | used as f64 / total as f64 178 | }; 179 | 180 | HardwareUsage { 181 | total, 182 | available, 183 | percentage_used, 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/logger/logger.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::thread; 3 | 4 | use super::atty; 5 | use super::colored::Colorize; 6 | use super::env_logger::filter::{Builder as FilterBuilder, Filter}; 7 | use super::time; 8 | 9 | use log::{LevelFilter, Log, Metadata, Record}; 10 | 11 | pub struct Logger { 12 | filter: Filter, 13 | } 14 | 15 | impl Logger { 16 | pub fn new() -> Self { 17 | let mut builder = FilterBuilder::new(); 18 | builder.filter(None, LevelFilter::Info); 19 | 20 | if let Ok(rust_log) = env::var("RUST_LOG") { 21 | builder.parse(&rust_log); 22 | } 23 | 24 | Self { 25 | filter: builder.build(), 26 | } 27 | } 28 | 29 | pub fn filter(&self) -> LevelFilter { 30 | self.filter.filter() 31 | } 32 | } 33 | 34 | impl Log for Logger { 35 | fn enabled(&self, metadata: &Metadata) -> bool { 36 | self.filter.enabled(metadata) 37 | } 38 | 39 | fn log(&self, record: &Record) { 40 | if self.filter.matches(record) { 41 | let thread_name = thread::current().name().unwrap_or_default().to_string(); 42 | let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap(); 43 | 44 | let stderr_isatty = atty::is(atty::Stream::Stderr); 45 | let timestamp = if stderr_isatty { 46 | timestamp.bold() 47 | } else { 48 | timestamp.normal() 49 | }; 50 | let thread_name = if stderr_isatty { 51 | thread_name.blue().bold() 52 | } else { 53 | thread_name.normal() 54 | }; 55 | let log_level = record.level(); 56 | let log_target = record.target(); 57 | let log_message = record.args(); 58 | eprintln!("#{} {} {} {} {}", timestamp, thread_name, log_level, log_target, log_message); 59 | } 60 | } 61 | 62 | fn flush(&self) {} 63 | } 64 | -------------------------------------------------------------------------------- /src/logger/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! log_target { 3 | (PROCESS) => { 4 | "agent-process" 5 | }; 6 | (MAIN) => { 7 | "agent-main" 8 | }; 9 | (WEB) => { 10 | "agent-web" 11 | }; 12 | (HARDWARE) => { 13 | "agent-hardware" 14 | }; 15 | } 16 | 17 | #[macro_export] 18 | macro_rules! clog { 19 | ($target:ident, $lvl:expr, $($arg:tt)+) => ({ 20 | log!(target: log_target!($target), $lvl, $($arg)*); 21 | }); 22 | } 23 | 24 | #[macro_export] 25 | macro_rules! cerror { 26 | ($target:ident, $($arg:tt)*) => ( 27 | clog!($target, $crate::logger::Level::Error, $($arg)*) 28 | ); 29 | } 30 | 31 | #[macro_export] 32 | macro_rules! cwarn { 33 | ($target:ident, $($arg:tt)*) => ( 34 | clog!($target, $crate::logger::Level::Warn, $($arg)*) 35 | ); 36 | } 37 | 38 | #[macro_export] 39 | macro_rules! cinfo { 40 | ($target:ident, $($arg:tt)*) => ( 41 | clog!($target, $crate::logger::Level::Info, $($arg)*) 42 | ); 43 | } 44 | 45 | #[macro_export] 46 | macro_rules! cdebug { 47 | ($target:ident, $($arg:tt)*) => ( 48 | clog!($target, $crate::logger::Level::Debug, $($arg)*) 49 | ); 50 | } 51 | 52 | #[macro_export] 53 | macro_rules! ctrace { 54 | ($target:ident, $($arg:tt)*) => ( 55 | clog!($target, $crate::logger::Level::Trace, $($arg)*) 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/logger/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate atty; 2 | extern crate colored; 3 | extern crate env_logger; 4 | extern crate time; 5 | 6 | #[cfg_attr(feature = "cargo-clippy", allow(clippy::module_inception))] 7 | mod logger; 8 | #[macro_use] 9 | pub mod macros; 10 | 11 | pub use log::Level; 12 | 13 | use self::logger::Logger; 14 | use log::SetLoggerError; 15 | 16 | pub fn init() -> Result<(), SetLoggerError> { 17 | let logger = Logger::new(); 18 | super::log::set_max_level(logger.filter()); 19 | super::log::set_boxed_logger(Box::new(logger)) 20 | } 21 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate clap; 3 | #[macro_use] 4 | extern crate log; 5 | extern crate parking_lot; 6 | #[macro_use] 7 | extern crate serde_derive; 8 | 9 | extern crate core; 10 | #[macro_use] 11 | extern crate crossbeam; 12 | extern crate jsonrpc_core; 13 | extern crate reqwest; 14 | extern crate serde; 15 | extern crate serde_json; 16 | extern crate subprocess; 17 | extern crate sysinfo; 18 | extern crate systemstat; 19 | extern crate ws; 20 | 21 | #[macro_use] 22 | mod logger; 23 | mod agent; 24 | mod handler; 25 | mod hardware_usage; 26 | mod process; 27 | mod rpc; 28 | mod types; 29 | 30 | use self::agent::run; 31 | use types::AgentArgs; 32 | 33 | fn main() { 34 | let yaml = load_yaml!("agent.yml"); 35 | let matches = clap::App::from_yaml(yaml).get_matches(); 36 | 37 | let codechain_dir = matches.value_of("codechain-dir").expect("codechain-dir is required option"); 38 | let log_file_path = matches.value_of("log-file").unwrap_or("agent.log"); 39 | let hub_url = matches.value_of("agent-hub-url").expect("agent-hub-url is required option"); 40 | let codechain_address = 41 | matches.value_of("codechain-p2p-address").expect("codechain-p2p-address is required option"); 42 | let codechain_address = codechain_address.parse().expect("codechain-p2p-address field's format is invalid"); 43 | let name = matches.value_of("name").expect("name is required option"); 44 | 45 | let args = AgentArgs { 46 | codechain_dir, 47 | log_file_path, 48 | hub_url, 49 | codechain_address, 50 | name, 51 | }; 52 | run(&args); 53 | } 54 | -------------------------------------------------------------------------------- /src/process/binary_update.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | use crossbeam; 4 | 5 | use super::fs_util; 6 | use super::update::{CallbackResult, Sender}; 7 | use super::Error; 8 | 9 | pub struct Job {} 10 | 11 | impl Job { 12 | pub fn run( 13 | codechain_dir: String, 14 | binary_url: String, 15 | binary_checksum: String, 16 | callback: crossbeam::Sender, 17 | ) -> Sender { 18 | thread::Builder::new() 19 | .name("binary update job".to_string()) 20 | .spawn(move || { 21 | let result = Self::update(codechain_dir, &binary_url, &binary_checksum); 22 | callback.send(result); 23 | }) 24 | .expect("Should success running update job thread") 25 | } 26 | 27 | fn update(codechain_dir: String, binary_url: &str, binary_checksum: &str) -> Result<(), Error> { 28 | if let Err(err) = fs_util::move_file(&codechain_dir, "codechain", "codechain.backup") { 29 | cwarn!(PROCESS, "Cannot move file codechain to codechain.backup: {:?}", err); 30 | } 31 | match Self::update_inner(&codechain_dir, binary_url, binary_checksum) { 32 | Ok(()) => Ok(()), 33 | Err(err) => { 34 | if let Err(move_err) = fs_util::move_file(&codechain_dir, "codechain.backup", "codechain") { 35 | cwarn!(PROCESS, "Cannot move file codechain.backup to codechain: {:?}", move_err); 36 | } 37 | Err(err) 38 | } 39 | } 40 | } 41 | 42 | fn update_inner(codechain_dir: &str, binary_url: &str, binary_checksum: &str) -> Result<(), Error> { 43 | fs_util::download_codechain(&codechain_dir, binary_url)?; 44 | fs_util::check_checksum(&codechain_dir, binary_checksum)?; 45 | fs_util::make_executable(&codechain_dir)?; 46 | Ok(()) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/process/codechain_process.rs: -------------------------------------------------------------------------------- 1 | extern crate libc; 2 | extern crate reopen; 3 | 4 | use std::fs::OpenOptions; 5 | use std::io::{self, Read, Write}; 6 | use std::path::Path; 7 | use std::sync::Arc; 8 | use std::thread; 9 | use std::time::Duration; 10 | 11 | use parking_lot::Mutex; 12 | use subprocess::{Exec, ExitStatus, Popen, PopenError, Redirection}; 13 | 14 | use super::ProcessOption; 15 | 16 | use self::reopen::Reopen; 17 | 18 | #[derive(Clone)] 19 | pub struct CodeChainProcess { 20 | process: Arc>, 21 | } 22 | 23 | impl CodeChainProcess { 24 | pub fn new(envs: Vec<(&str, &str)>, args: Vec, option: &ProcessOption) -> Result { 25 | let log_file_path = option.log_file_path.clone(); 26 | let mut file = 27 | Reopen::new(Box::new(move || OpenOptions::new().append(true).create(true).open(log_file_path.clone()))) 28 | .map_err(|err| err.to_string())?; 29 | file.handle().register_signal(libc::SIGHUP).unwrap(); 30 | 31 | let mut exec = if Path::new(&option.codechain_dir).join("codechain").exists() { 32 | Exec::cmd("./codechain") 33 | .cwd(option.codechain_dir.clone()) 34 | .stdout(Redirection::Pipe) 35 | .stderr(Redirection::Merge) 36 | .args(&args) 37 | } else { 38 | Exec::cmd("cargo") 39 | .arg("run") 40 | .arg("--") 41 | .cwd(option.codechain_dir.clone()) 42 | .stdout(Redirection::Pipe) 43 | .stderr(Redirection::Merge) 44 | .args(&args) 45 | }; 46 | 47 | for (k, v) in envs { 48 | exec = exec.env(k, v); 49 | } 50 | 51 | let child = exec.popen().map_err(|err| err.to_string())?; 52 | 53 | let process = CodeChainProcess { 54 | process: Arc::new(Mutex::new(child)), 55 | }; 56 | 57 | let process_in_thread = process.clone(); 58 | 59 | thread::Builder::new() 60 | .name("codechain_log_writer".to_string()) 61 | .spawn(move || { 62 | let mut buf: [u8; 1024] = [0; 1024]; 63 | loop { 64 | let length = match process_in_thread.read(&mut buf) { 65 | Ok(length) => length, 66 | Err(err) => { 67 | cerror!(PROCESS, "Fail to read stdout of CodeChain : {}", err); 68 | return 69 | } 70 | }; 71 | 72 | if let Err(err) = file.write_all(&buf[0..length]) { 73 | cerror!(PROCESS, "Fail to write stdout of CodeChain : {}", err); 74 | return 75 | } 76 | } 77 | }) 78 | .expect("Should success running process thread"); 79 | 80 | Ok(process) 81 | } 82 | 83 | pub fn read(&self, buf: &mut [u8]) -> Result { 84 | let mut process = self.process.lock(); 85 | process.stdout.as_mut().expect("Process opened with pipe").read(buf) 86 | } 87 | 88 | pub fn is_running(&self) -> bool { 89 | let mut process = self.process.lock(); 90 | process.poll().is_none() 91 | } 92 | 93 | pub fn terminate(&self) -> Result<(), io::Error> { 94 | let mut process = self.process.lock(); 95 | process.terminate() 96 | } 97 | 98 | pub fn wait_timeout(&self, duration: Duration) -> Result, PopenError> { 99 | let mut process = self.process.lock(); 100 | process.wait_timeout(duration) 101 | } 102 | 103 | pub fn kill(&self) -> Result<(), io::Error> { 104 | let mut process = self.process.lock(); 105 | process.kill() 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/process/fs_util.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use subprocess::Exec; 4 | 5 | use super::Error; 6 | 7 | pub fn move_file(dir: &str, from: &str, to: &str) -> Result<(), Error> { 8 | cdebug!(PROCESS, "Move {} to {}", from, to); 9 | let exec = Exec::cmd("mv").arg(from).arg(to).cwd(dir).capture()?; 10 | if exec.exit_status.success() { 11 | Ok(()) 12 | } else { 13 | Err(Error::ShellError { 14 | exit_code: exec.exit_status, 15 | stdout: exec.stdout_str(), 16 | stderr: exec.stderr_str(), 17 | }) 18 | } 19 | } 20 | 21 | pub fn download_codechain(codechain_dir: &str, codechain_url: &str) -> Result<(), Error> { 22 | cdebug!(PROCESS, "RUN wget {}", codechain_url); 23 | let exec = Exec::cmd("wget").arg(codechain_url).cwd(codechain_dir).capture()?; 24 | if exec.exit_status.success() { 25 | Ok(()) 26 | } else { 27 | Err(Error::ShellError { 28 | exit_code: exec.exit_status, 29 | stdout: exec.stdout_str(), 30 | stderr: exec.stderr_str(), 31 | }) 32 | } 33 | } 34 | 35 | pub fn make_executable(codechain_dir: &str) -> Result<(), Error> { 36 | cdebug!(PROCESS, "Run cmod +x codechain"); 37 | let exec = Exec::cmd("chmod").arg("+x").arg("codechain").cwd(codechain_dir).capture()?; 38 | if exec.exit_status.success() { 39 | Ok(()) 40 | } else { 41 | Err(Error::ShellError { 42 | exit_code: exec.exit_status, 43 | stdout: exec.stdout_str(), 44 | stderr: exec.stderr_str(), 45 | }) 46 | } 47 | } 48 | 49 | pub fn check_checksum(codechain_dir: &str, binary_checksum: &str) -> Result<(), Error> { 50 | cdebug!(PROCESS, "Run shasum codechain | awk '{{ print $1 }}'"); 51 | let shasum = Exec::cmd("shasum").arg("codechain").cwd(codechain_dir); 52 | let get_1_column = Exec::cmd("awk").arg("{ print $1 }").cwd(codechain_dir); 53 | let calculated_checksum = { shasum | get_1_column }.capture()?; 54 | 55 | if !calculated_checksum.exit_status.success() { 56 | return Err(Error::ShellError { 57 | exit_code: calculated_checksum.exit_status, 58 | stdout: calculated_checksum.stdout_str(), 59 | stderr: "".to_string(), 60 | }) 61 | } 62 | 63 | if calculated_checksum.stdout_str().trim() != binary_checksum.trim() { 64 | return Err(Error::BinaryChecksumMismatch { 65 | expected: binary_checksum.trim().to_string(), 66 | actual: calculated_checksum.stdout_str().trim().to_string(), 67 | }) 68 | } 69 | 70 | Ok(()) 71 | } 72 | 73 | pub fn get_checksum_or_default(dir: &str, file: &str) -> Result { 74 | let path = Path::new(dir).join(file); 75 | if !path.exists() { 76 | return Ok("".to_string()) 77 | } 78 | 79 | cdebug!(PROCESS, "Run shasum {:?}", path); 80 | let exec = Exec::cmd("shasum").arg("-a").arg("256").arg(file).cwd(dir).capture()?; 81 | 82 | if exec.exit_status.success() { 83 | Ok(exec.stdout_str().trim().to_string()) 84 | } else { 85 | Err(Error::ShellError { 86 | exit_code: exec.exit_status, 87 | stdout: exec.stdout_str(), 88 | stderr: exec.stderr_str(), 89 | }) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/process/git_update.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | use crossbeam; 4 | 5 | use super::super::types::CommitHash; 6 | use super::git_util; 7 | use super::update::{CallbackResult, Sender}; 8 | use super::Error; 9 | 10 | pub struct Job {} 11 | 12 | impl Job { 13 | pub fn run(codechain_dir: String, commit_hash: CommitHash, callback: crossbeam::Sender) -> Sender { 14 | thread::Builder::new() 15 | .name("git update job".to_string()) 16 | .spawn(move || { 17 | let result = Self::update(codechain_dir, &commit_hash); 18 | callback.send(result); 19 | }) 20 | .expect("Should success running update job thread") 21 | } 22 | 23 | fn update(codechain_dir: String, commit_hash: &str) -> Result<(), Error> { 24 | git_util::remote_update(codechain_dir.clone())?; 25 | git_util::reset_hard(codechain_dir.clone(), commit_hash.to_string())?; 26 | let current_hash = git_util::current_hash(codechain_dir)?; 27 | if commit_hash != current_hash { 28 | cwarn!(PROCESS, "Updated commit hash not matched expected {} found {}", commit_hash, current_hash); 29 | Err(Error::Unknown(format!("Cannot update to {}", commit_hash))) 30 | } else { 31 | Ok(()) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/process/git_util.rs: -------------------------------------------------------------------------------- 1 | use super::super::types::CommitHash; 2 | use super::Error; 3 | use super::Exec; 4 | 5 | pub fn current_hash(codechain_dir: String) -> Result { 6 | cdebug!(PROCESS, "Run git rev-parse HEAD at {}", codechain_dir); 7 | let result = match Exec::cmd("git").arg("rev-parse").arg("HEAD").cwd(codechain_dir).capture() { 8 | Ok(exec) => exec.stdout_str().trim().to_string(), 9 | Err(err) => { 10 | cwarn!(PROCESS, "Cannot get git hash {}", err); 11 | "NONE".to_string() 12 | } 13 | }; 14 | Ok(result) 15 | } 16 | 17 | pub fn remote_update(codechain_dir: String) -> Result<(), Error> { 18 | cinfo!(PROCESS, "Run git remote update"); 19 | let exec = Exec::cmd("git").arg("remote").arg("update").cwd(codechain_dir).capture()?; 20 | if exec.exit_status.success() { 21 | ctrace!(PROCESS, "git remote update\n stdout: {}\n stderr: {}\n", exec.stdout_str(), exec.stderr_str()); 22 | Ok(()) 23 | } else { 24 | Err(Error::ShellError { 25 | exit_code: exec.exit_status, 26 | stdout: exec.stdout_str(), 27 | stderr: exec.stderr_str(), 28 | }) 29 | } 30 | } 31 | 32 | pub fn reset_hard(codechain_dir: String, target_commit_hash: CommitHash) -> Result<(), Error> { 33 | cinfo!(PROCESS, "Run git reset --hard"); 34 | let exec = Exec::cmd("git").arg("reset").arg("--hard").arg(target_commit_hash).cwd(codechain_dir).capture()?; 35 | if exec.exit_status.success() { 36 | ctrace!(PROCESS, "git remote update\n stdout: {}\n stderr: {}\n", exec.stdout_str(), exec.stderr_str()); 37 | Ok(()) 38 | } else { 39 | Err(Error::ShellError { 40 | exit_code: exec.exit_status, 41 | stdout: exec.stdout_str(), 42 | stderr: exec.stderr_str(), 43 | }) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/process/mod.rs: -------------------------------------------------------------------------------- 1 | mod binary_update; 2 | mod codechain_process; 3 | mod fs_util; 4 | mod git_update; 5 | mod git_util; 6 | mod rpc; 7 | mod update; 8 | 9 | use std::cell::Cell; 10 | use std::io::Error as IOError; 11 | use std::option::Option; 12 | use std::result::Result; 13 | use std::sync::Arc; 14 | use std::thread; 15 | use std::time::Duration; 16 | 17 | use crossbeam::channel; 18 | use crossbeam::channel::{Receiver, Sender}; 19 | use parking_lot::Mutex; 20 | use serde_json::Value; 21 | use subprocess::{Exec, ExitStatus, PopenError}; 22 | 23 | use self::codechain_process::CodeChainProcess; 24 | use super::rpc::types::{NodeStatus, UpdateCodeChainRequest}; 25 | use super::types::CommitHash; 26 | 27 | #[derive(Debug)] 28 | pub enum Error { 29 | EnvParseError, 30 | AlreadyRunning, 31 | NotRunning, 32 | // CodeChain is now updating, cannot run or stop CodeChain when updating 33 | Updating, 34 | SubprocessError(PopenError), 35 | IO(IOError), 36 | ShellError { 37 | exit_code: ExitStatus, 38 | stdout: String, 39 | stderr: String, 40 | }, 41 | BinaryChecksumMismatch { 42 | expected: String, 43 | actual: String, 44 | }, 45 | // This error caused when sending HTTP request to the codechain 46 | CodeChainRPC(String), 47 | Unknown(String), 48 | } 49 | 50 | impl From for Error { 51 | fn from(error: PopenError) -> Self { 52 | Error::SubprocessError(error) 53 | } 54 | } 55 | 56 | impl From for Error { 57 | fn from(error: IOError) -> Self { 58 | Error::IO(error) 59 | } 60 | } 61 | 62 | pub struct ProcessOption { 63 | pub codechain_dir: String, 64 | pub log_file_path: String, 65 | } 66 | 67 | enum CodeChainStatus { 68 | Starting { 69 | p2p_port: u16, 70 | rpc_client: rpc::RPCClient, 71 | }, 72 | Run { 73 | p2p_port: u16, 74 | rpc_client: rpc::RPCClient, 75 | }, 76 | Updating { 77 | env: String, 78 | args: String, 79 | sender: Cell>, 80 | rx_callback: Receiver, 81 | }, 82 | Stop, 83 | Error { 84 | p2p_port: u16, 85 | rpc_client: Option, 86 | }, 87 | Temp, 88 | } 89 | 90 | impl CodeChainStatus { 91 | fn to_node_status(&self) -> NodeStatus { 92 | match self { 93 | CodeChainStatus::Starting { 94 | .. 95 | } => NodeStatus::Starting, 96 | CodeChainStatus::Run { 97 | .. 98 | } => NodeStatus::Run, 99 | CodeChainStatus::Stop => NodeStatus::Stop, 100 | CodeChainStatus::Updating { 101 | .. 102 | } => NodeStatus::Updating, 103 | CodeChainStatus::Error { 104 | .. 105 | } => NodeStatus::Error, 106 | CodeChainStatus::Temp => unreachable!(), 107 | } 108 | } 109 | 110 | fn p2p_port(&self) -> Option { 111 | match self { 112 | CodeChainStatus::Starting { 113 | p2p_port, 114 | .. 115 | } => Some(*p2p_port), 116 | CodeChainStatus::Run { 117 | p2p_port, 118 | .. 119 | } => Some(*p2p_port), 120 | CodeChainStatus::Stop => None, 121 | CodeChainStatus::Updating { 122 | .. 123 | } => None, 124 | CodeChainStatus::Error { 125 | p2p_port, 126 | .. 127 | } => Some(*p2p_port), 128 | CodeChainStatus::Temp => unreachable!(), 129 | } 130 | } 131 | 132 | fn rpc_client(&self) -> Option<&rpc::RPCClient> { 133 | match self { 134 | CodeChainStatus::Starting { 135 | rpc_client, 136 | .. 137 | } => Some(rpc_client), 138 | CodeChainStatus::Run { 139 | rpc_client, 140 | .. 141 | } => Some(rpc_client), 142 | CodeChainStatus::Stop => None, 143 | CodeChainStatus::Updating { 144 | .. 145 | } => None, 146 | CodeChainStatus::Error { 147 | rpc_client, 148 | .. 149 | } => rpc_client.as_ref(), 150 | CodeChainStatus::Temp => unreachable!(), 151 | } 152 | } 153 | 154 | fn is_updating(&self) -> bool { 155 | if let CodeChainStatus::Updating { 156 | .. 157 | } = self 158 | { 159 | true 160 | } else { 161 | false 162 | } 163 | } 164 | } 165 | 166 | type Callback = Sender>; 167 | 168 | pub struct ProcessGetStatusResult { 169 | pub status: NodeStatus, 170 | pub port: Option, 171 | pub commit_hash: CommitHash, 172 | pub binary_checksum: String, 173 | } 174 | 175 | pub enum Message { 176 | Run { 177 | env: String, 178 | args: String, 179 | callback: Callback<()>, 180 | }, 181 | Stop { 182 | callback: Callback<()>, 183 | }, 184 | #[allow(dead_code)] 185 | Quit { 186 | callback: Callback<()>, 187 | }, 188 | Update { 189 | env: String, 190 | args: String, 191 | target: UpdateCodeChainRequest, 192 | callback: Callback<()>, 193 | }, 194 | GetStatus { 195 | callback: Callback, 196 | }, 197 | GetLog { 198 | levels: Vec, 199 | callback: Callback>, 200 | }, 201 | CallRPC { 202 | method: String, 203 | arguments: Vec, 204 | callback: Callback, 205 | }, 206 | } 207 | 208 | pub fn spawn(option: ProcessOption) -> Sender { 209 | let codechain_status: Arc> = Arc::new(Mutex::new(CodeChainStatus::Stop)); 210 | let child: Arc>> = Default::default(); 211 | 212 | let (tx, rx) = channel::unbounded(); 213 | let cloned_child = Arc::clone(&child); 214 | let cloned_codechain_status = Arc::clone(&codechain_status); 215 | thread::Builder::new() 216 | .name("process".to_string()) 217 | .spawn(move || loop { 218 | let message = rx.recv().unwrap(); 219 | handle_message(message, &option, cloned_codechain_status.as_ref(), cloned_child.as_ref()); 220 | }) 221 | .expect("Should success running process thread"); 222 | 223 | let cloned_tx = tx.clone(); 224 | thread::Builder::new() 225 | .name("heartbeat".to_string()) 226 | .spawn(move || loop { 227 | let one_second = Duration::from_secs(1); 228 | channel::after(one_second).recv().unwrap(); 229 | ping_to_codechain(codechain_status.as_ref(), child.as_ref()); 230 | if let Some((env, args)) = handle_update(codechain_status.as_ref()) { 231 | let (callback, recv) = channel::bounded(1); 232 | cloned_tx.send(Message::Run { 233 | env, 234 | args, 235 | callback, 236 | }); 237 | if let Err(err) = recv.recv().unwrap() { 238 | cerror!(PROCESS, "Cannot run codechain after update : {:?}", err); 239 | } 240 | } 241 | }) 242 | .expect("Should success running heartbeat thread"); 243 | tx 244 | } 245 | 246 | fn handle_message( 247 | message: Message, 248 | option: &ProcessOption, 249 | codechain_status: &Mutex, 250 | child: &Mutex>, 251 | ) { 252 | match message { 253 | Message::Run { 254 | env, 255 | args, 256 | callback, 257 | } => { 258 | let result = run(&env, &args, option, &mut codechain_status.lock(), child); 259 | callback.send(result); 260 | } 261 | Message::Stop { 262 | callback, 263 | } => { 264 | let result = stop(&mut *codechain_status.lock(), child); 265 | callback.send(result); 266 | } 267 | Message::Quit { 268 | callback, 269 | } => { 270 | let result = stop(&mut *codechain_status.lock(), child); 271 | if let CodeChainStatus::Updating { 272 | sender, 273 | .. 274 | } = &*codechain_status.lock() 275 | { 276 | cinfo!(PROCESS, "Wait until codechain update finish"); 277 | let moved_sender = sender.replace(None).expect("Sender should be exist"); 278 | if let Err(err) = moved_sender.join() { 279 | cerror!(PROCESS, "Cannot wait for git update closing: {:?}", err); 280 | } 281 | } 282 | callback.send(result); 283 | return 284 | } 285 | Message::Update { 286 | env, 287 | args, 288 | target, 289 | callback, 290 | } => { 291 | let mut codechain_status = codechain_status.lock(); 292 | let result = if check_running(&*child.lock()) { 293 | stop(&mut *codechain_status, child) 294 | } else { 295 | Ok(()) 296 | }; 297 | let result = result.and_then(|_| update(option, &target, env, args, &mut *codechain_status)); 298 | callback.send(result); 299 | } 300 | Message::GetStatus { 301 | callback, 302 | } => { 303 | let codechain_status = codechain_status.lock(); 304 | let status = codechain_status.to_node_status(); 305 | let p2p_port = codechain_status.p2p_port(); 306 | let commit_hash = get_commit_hash(option, &*codechain_status).unwrap_or_default(); 307 | let binary_checksum = 308 | fs_util::get_checksum_or_default(&option.codechain_dir, "codechain").unwrap_or_default(); 309 | callback.send(Ok(ProcessGetStatusResult { 310 | status, 311 | port: p2p_port, 312 | commit_hash, 313 | binary_checksum, 314 | })); 315 | } 316 | Message::GetLog { 317 | levels, 318 | callback, 319 | } => { 320 | let result = get_log(levels, &*codechain_status.lock()); 321 | callback.send(result); 322 | } 323 | Message::CallRPC { 324 | method, 325 | arguments, 326 | callback, 327 | } => match codechain_status.lock().rpc_client() { 328 | Some(rpc_client) => { 329 | let result = rpc_client.call_rpc(method, arguments).map_err(|err| Error::CodeChainRPC(err.to_string())); 330 | callback.send(result) 331 | } 332 | None => callback.send(Err(Error::NotRunning)), 333 | }, 334 | } 335 | } 336 | 337 | fn ping_to_codechain(codechain_status: &Mutex, child: &Mutex>) { 338 | let mut codechain_status = codechain_status.lock(); 339 | if let CodeChainStatus::Stop = *codechain_status { 340 | return 341 | } 342 | 343 | if let CodeChainStatus::Updating { 344 | .. 345 | } = *codechain_status 346 | { 347 | return 348 | } 349 | 350 | ctrace!(PROCESS, "Ping to CodeChain"); 351 | 352 | let result = match codechain_status.rpc_client() { 353 | Some(rpc_client) => Some(rpc_client.call_rpc("ping".to_string(), Vec::new())), 354 | None => None, 355 | }; 356 | ctrace!(PROCESS, "{:?}", result); 357 | 358 | let original: CodeChainStatus = ::std::mem::replace(&mut *codechain_status, CodeChainStatus::Temp); 359 | let next_status: CodeChainStatus = match original { 360 | CodeChainStatus::Run { 361 | p2p_port, 362 | rpc_client, 363 | } => { 364 | if let Err(err) = result.unwrap() { 365 | cinfo!(PROCESS, "Codechain ping error {:#?}", err); 366 | CodeChainStatus::Error { 367 | p2p_port, 368 | rpc_client: Some(rpc_client), 369 | } 370 | } else { 371 | CodeChainStatus::Run { 372 | p2p_port, 373 | rpc_client, 374 | } 375 | } 376 | } 377 | CodeChainStatus::Starting { 378 | p2p_port, 379 | rpc_client, 380 | } => { 381 | if result.unwrap().is_ok() { 382 | cinfo!(PROCESS, "CodeChain is running now"); 383 | CodeChainStatus::Run { 384 | p2p_port, 385 | rpc_client, 386 | } 387 | } else if !check_running(&*child.lock()) { 388 | CodeChainStatus::Error { 389 | p2p_port, 390 | rpc_client: Some(rpc_client), 391 | } 392 | } else { 393 | CodeChainStatus::Starting { 394 | p2p_port, 395 | rpc_client, 396 | } 397 | } 398 | } 399 | CodeChainStatus::Stop => unreachable!(), 400 | CodeChainStatus::Error { 401 | p2p_port, 402 | rpc_client, 403 | } => { 404 | if let Some(Ok(_)) = result { 405 | cinfo!(PROCESS, "CodeChain returned to normal"); 406 | CodeChainStatus::Run { 407 | p2p_port, 408 | rpc_client: rpc_client.unwrap(), 409 | } 410 | } else { 411 | CodeChainStatus::Error { 412 | p2p_port, 413 | rpc_client, 414 | } 415 | } 416 | } 417 | CodeChainStatus::Updating { 418 | .. 419 | } => unreachable!(), 420 | CodeChainStatus::Temp => unreachable!(), 421 | }; 422 | 423 | *codechain_status = next_status; 424 | } 425 | 426 | fn handle_update(codechain_status: &Mutex) -> Option<(String, String)> { 427 | let mut codechain_status = codechain_status.lock(); 428 | let result = if let CodeChainStatus::Updating { 429 | rx_callback, 430 | env, 431 | args, 432 | .. 433 | } = &*codechain_status 434 | { 435 | match rx_callback.try_recv()? { 436 | Err(err) => { 437 | cinfo!(PROCESS, "Update failed : {:?}", err); 438 | None 439 | } 440 | Ok(_) => { 441 | cinfo!(PROCESS, "Update success"); 442 | Some((env.clone(), args.clone())) 443 | } 444 | } 445 | } else { 446 | return None 447 | }; 448 | if let Some((env, args)) = result { 449 | *codechain_status = CodeChainStatus::Stop; 450 | Some((env, args)) 451 | } else { 452 | *codechain_status = CodeChainStatus::Error { 453 | p2p_port: 0, 454 | rpc_client: None, 455 | }; 456 | None 457 | } 458 | } 459 | 460 | fn run( 461 | env: &str, 462 | args: &str, 463 | option: &ProcessOption, 464 | codechain_status: &mut CodeChainStatus, 465 | child: &Mutex>, 466 | ) -> Result<(), Error> { 467 | cinfo!(PROCESS, "Run codechain"); 468 | if check_running(&*child.lock()) { 469 | cinfo!(PROCESS, "Run codechain failed because it is AlreadyRunning"); 470 | return Err(Error::AlreadyRunning) 471 | } 472 | if codechain_status.is_updating() { 473 | cinfo!(PROCESS, "Run codechain failed because it is Updating"); 474 | return Err(Error::Updating) 475 | } 476 | 477 | let args_iter = args.split_whitespace(); 478 | let args_vec: Vec = args_iter.map(|str| str.to_string()).collect(); 479 | let (p2p_port, rpc_port) = parse_ports(&args_vec); 480 | let envs = parse_env(env)?; 481 | 482 | *child.lock() = Some(CodeChainProcess::new(envs, args_vec, option).map_err(Error::Unknown)?); 483 | 484 | *codechain_status = CodeChainStatus::Starting { 485 | p2p_port, 486 | rpc_client: rpc::RPCClient::new(rpc_port), 487 | }; 488 | 489 | Ok(()) 490 | } 491 | 492 | fn check_running(child: &Option) -> bool { 493 | child.as_ref().map_or(false, |child| child.is_running()) 494 | } 495 | 496 | fn parse_env(env: &str) -> Result, Error> { 497 | let env_kvs = env.split_whitespace(); 498 | let mut ret = Vec::new(); 499 | for env_kv in env_kvs { 500 | let kv_array: Vec<&str> = env_kv.splitn(2, '=').collect(); 501 | if kv_array.len() != 2 { 502 | return Err(Error::EnvParseError) 503 | } else { 504 | ret.push((kv_array[0], kv_array[1])); 505 | } 506 | } 507 | Ok(ret) 508 | } 509 | 510 | fn stop(codechain_status: &mut CodeChainStatus, child: &Mutex>) -> Result<(), Error> { 511 | let child = child.lock(); 512 | if !check_running(&*child) { 513 | return Err(Error::NotRunning) 514 | } 515 | if codechain_status.is_updating() { 516 | return Err(Error::Updating) 517 | } 518 | 519 | cinfo!(PROCESS, "Stop CodeChain"); 520 | 521 | let codechain = child.as_ref().expect("Already checked"); 522 | ctrace!(PROCESS, "Send SIGTERM to CodeChain"); 523 | codechain.terminate()?; 524 | 525 | let wait_result = codechain.wait_timeout(Duration::new(10, 0))?; 526 | 527 | if let Some(exit_code) = wait_result { 528 | ctrace!(PROCESS, "CodeChain closed with {:?}", exit_code); 529 | *codechain_status = CodeChainStatus::Stop; 530 | return Ok(()) 531 | } 532 | 533 | cinfo!(PROCESS, "CodeChain does not exit after 10 seconds"); 534 | 535 | codechain.kill()?; 536 | 537 | *codechain_status = CodeChainStatus::Stop; 538 | 539 | Ok(()) 540 | } 541 | 542 | fn update( 543 | option: &ProcessOption, 544 | target: &UpdateCodeChainRequest, 545 | env: String, 546 | args: String, 547 | codechain_status: &mut CodeChainStatus, 548 | ) -> Result<(), Error> { 549 | if codechain_status.is_updating() { 550 | return Err(Error::Updating) 551 | } 552 | 553 | cinfo!(PROCESS, "Update CodeChain"); 554 | 555 | let (tx, rx) = channel::unbounded(); 556 | let job_sender = match target { 557 | UpdateCodeChainRequest::Git { 558 | commit_hash, 559 | } => git_update::Job::run(option.codechain_dir.to_string(), commit_hash.to_string(), tx), 560 | UpdateCodeChainRequest::Binary { 561 | binary_url, 562 | binary_checksum, 563 | } => binary_update::Job::run( 564 | option.codechain_dir.to_string(), 565 | binary_url.to_string(), 566 | binary_checksum.to_string(), 567 | tx, 568 | ), 569 | }; 570 | 571 | *codechain_status = CodeChainStatus::Updating { 572 | env, 573 | args, 574 | sender: Cell::new(Some(job_sender)), 575 | rx_callback: rx, 576 | }; 577 | 578 | Ok(()) 579 | } 580 | 581 | fn get_log(levels: Vec, codechain_status: &CodeChainStatus) -> Result, Error> { 582 | let rpc_client = match codechain_status.rpc_client() { 583 | Some(rpc_client) => rpc_client, 584 | None => return Err(Error::NotRunning), 585 | }; 586 | let mut response = 587 | rpc_client.call_rpc("slog".to_string(), Vec::new()).map_err(|err| Error::CodeChainRPC(err.to_string()))?; 588 | let result = response 589 | .get_mut("result") 590 | .ok_or_else(|| Error::CodeChainRPC("JSON parse failed: cannot find the result field".to_string()))?; 591 | let logs = result 592 | .as_array_mut() 593 | .ok_or_else(|| Error::CodeChainRPC("JSON parse failed: slog's result is not array".to_string()))?; 594 | 595 | let empty_string = Value::String("".to_string()); 596 | let filtered_logs = logs 597 | .iter_mut() 598 | .filter(|log| { 599 | let target = log.pointer("/level").unwrap_or(&empty_string).as_str().unwrap_or(""); 600 | levels.iter().any(|t| target.to_lowercase() == t.to_lowercase()) 601 | }) 602 | .map(|value| value.take()); 603 | 604 | Ok(filtered_logs.collect()) 605 | } 606 | 607 | fn get_commit_hash(option: &ProcessOption, codechain_status: &CodeChainStatus) -> Result { 608 | if let CodeChainStatus::Run { 609 | rpc_client, 610 | .. 611 | } = &codechain_status 612 | { 613 | let response = rpc_client 614 | .call_rpc("commitHash".to_string(), Vec::new()) 615 | .map_err(|err| Error::CodeChainRPC(err.to_string()))?; 616 | Ok(response["result"].as_str().unwrap_or("").to_string()) 617 | } else { 618 | Ok(git_util::current_hash(option.codechain_dir.clone())?) 619 | } 620 | } 621 | 622 | fn parse_ports(args: &[String]) -> (u16, u16) { 623 | let p2p_port = parse_port(args, "--port"); 624 | let rpc_port = parse_port(args, "--jsonrpc-port"); 625 | 626 | (p2p_port.unwrap_or(3485), rpc_port.unwrap_or(8080)) 627 | } 628 | 629 | fn parse_port(args: &[String], option_name: &str) -> Option { 630 | let option_position = args.iter().position(|arg| arg == option_name); 631 | let interface_pos = option_position.map(|pos| pos + 1); 632 | let interface_string = interface_pos.and_then(|pos| args.get(pos)); 633 | interface_string.and_then(|port| port.parse().ok()) 634 | } 635 | -------------------------------------------------------------------------------- /src/process/rpc.rs: -------------------------------------------------------------------------------- 1 | use jsonrpc_core; 2 | use jsonrpc_core::types::Version; 3 | use reqwest; 4 | use serde_json::Value; 5 | use std::time::Duration; 6 | 7 | #[derive(Debug)] 8 | pub enum CallRPCError { 9 | Web(reqwest::Error), 10 | Format(String), 11 | } 12 | 13 | impl ::std::error::Error for CallRPCError {} 14 | 15 | impl ::std::fmt::Display for CallRPCError { 16 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { 17 | match self { 18 | CallRPCError::Web(err) => write!(f, "Web request error while sending RPC to CodeChain: {}", err), 19 | CallRPCError::Format(err) => write!(f, "Cannot parse CodeChain's response as JSON: {}", err), 20 | } 21 | } 22 | } 23 | 24 | pub struct RPCClient { 25 | rpc_port: u16, 26 | http_client: reqwest::Client, 27 | } 28 | 29 | impl RPCClient { 30 | pub fn new(rpc_port: u16) -> Self { 31 | let http_client = reqwest::Client::builder().gzip(true).timeout(Duration::from_secs(1)).build().unwrap(); 32 | Self { 33 | rpc_port, 34 | http_client, 35 | } 36 | } 37 | 38 | /// Return JSONRPC response object 39 | /// Example: {"jsonrpc": "2.0", "result": 19, "id": 1} 40 | pub fn call_rpc(&self, method: String, arguments: Vec) -> Result { 41 | let params = jsonrpc_core::Params::Array(arguments); 42 | 43 | let jsonrpc_request = jsonrpc_core::MethodCall { 44 | jsonrpc: Some(Version::V2), 45 | method, 46 | params: Some(params), 47 | id: jsonrpc_core::Id::Num(1), 48 | }; 49 | 50 | ctrace!(PROCESS, "Send JSONRPC to CodeChain {:#?}", jsonrpc_request); 51 | 52 | let url = format!("http://127.0.0.1:{}/", self.rpc_port); 53 | let mut response = self.http_client.post(&url).json(&jsonrpc_request).send().map_err(CallRPCError::Web)?; 54 | 55 | let response: jsonrpc_core::Response = response.json().map_err(|err| CallRPCError::Format(err.to_string()))?; 56 | 57 | ctrace!(PROCESS, "Recieve JSONRPC response from CodeChain {:#?}", response); 58 | let value = serde_json::to_value(response).expect("Should success jsonrpc type to Value"); 59 | 60 | Ok(value) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/process/update.rs: -------------------------------------------------------------------------------- 1 | use super::Error; 2 | use std::thread::JoinHandle; 3 | 4 | pub type Sender = JoinHandle<()>; 5 | pub type CallbackResult = Result<(), Error>; 6 | -------------------------------------------------------------------------------- /src/rpc/api.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | 3 | use crossbeam::channel; 4 | use serde_json::Value; 5 | 6 | use super::super::hardware_usage::HardwareInfo; 7 | use super::super::process::{Error as ProcessError, Message as ProcessMessage, ProcessGetStatusResult}; 8 | use super::super::types::HandlerContext; 9 | use super::router::Router; 10 | use super::types::{ 11 | response, AgentGetInfoResponse, CodeChainCallRPCResponse, RPCResult, ShellGetCodeChainLogRequest, 12 | ShellStartCodeChainRequest, UpdateCodeChainRequest, 13 | }; 14 | use rpc::types::RPCError; 15 | use rpc::types::ERR_NETWORK_ERROR; 16 | 17 | pub fn add_routing(router: &mut Router) { 18 | router.add_route("ping", Box::new(ping as fn(&HandlerContext) -> RPCResult)); 19 | router.add_route( 20 | "shell_startCodeChain", 21 | Box::new(shell_start_codechain as fn(&HandlerContext, (ShellStartCodeChainRequest,)) -> RPCResult<()>), 22 | ); 23 | router.add_route("shell_stopCodeChain", Box::new(shell_stop_codechain as fn(&HandlerContext) -> RPCResult<()>)); 24 | router.add_route( 25 | "shell_updateCodeChain", 26 | Box::new( 27 | shell_update_codechain 28 | as fn(&HandlerContext, (ShellStartCodeChainRequest, UpdateCodeChainRequest)) -> RPCResult<()>, 29 | ), 30 | ); 31 | router.add_route( 32 | "shell_getCodeChainLog", 33 | Box::new( 34 | shell_get_codechain_log as fn(&HandlerContext, (ShellGetCodeChainLogRequest,)) -> RPCResult>, 35 | ), 36 | ); 37 | router 38 | .add_route("agent_getInfo", Box::new(agent_get_info as fn(&HandlerContext) -> RPCResult)); 39 | router.add_route( 40 | "codechain_callRPC", 41 | Box::new( 42 | codechain_call_rpc as fn(&HandlerContext, (String, Vec)) -> RPCResult, 43 | ), 44 | ); 45 | router.add_route("hardware_get", Box::new(hardware_get as fn(&HandlerContext) -> RPCResult)); 46 | } 47 | 48 | fn ping(_context: &HandlerContext) -> RPCResult { 49 | response("pong".to_string()) 50 | } 51 | 52 | fn shell_start_codechain(context: &HandlerContext, req: (ShellStartCodeChainRequest,)) -> RPCResult<()> { 53 | let (req,) = req; 54 | 55 | let (tx, rx) = channel::unbounded(); 56 | context.process.send(ProcessMessage::Run { 57 | env: req.env, 58 | args: req.args, 59 | callback: tx, 60 | }); 61 | let process_result = rx.recv(); 62 | process_result.ok_or_else(|| RPCError::Internal("Cannot receive process result".to_string()))??; 63 | response(()) 64 | } 65 | 66 | fn shell_stop_codechain(context: &HandlerContext) -> RPCResult<()> { 67 | let (tx, rx) = channel::unbounded(); 68 | context.process.send(ProcessMessage::Stop { 69 | callback: tx, 70 | }); 71 | let process_result = rx.recv(); 72 | process_result.ok_or_else(|| RPCError::Internal("Cannot receive process result".to_string()))??; 73 | response(()) 74 | } 75 | 76 | fn shell_update_codechain( 77 | context: &HandlerContext, 78 | req: (ShellStartCodeChainRequest, UpdateCodeChainRequest), 79 | ) -> RPCResult<()> { 80 | let (start_req, update_req) = req; 81 | 82 | let (tx, rx) = channel::unbounded(); 83 | context.process.send(ProcessMessage::Update { 84 | env: start_req.env, 85 | args: start_req.args, 86 | target: update_req, 87 | callback: tx, 88 | }); 89 | let process_result = rx.recv(); 90 | process_result.ok_or_else(|| RPCError::Internal("Cannot receive process result".to_string()))??; 91 | response(()) 92 | } 93 | 94 | fn shell_get_codechain_log(context: &HandlerContext, req: (ShellGetCodeChainLogRequest,)) -> RPCResult> { 95 | let (tx, rx) = channel::unbounded(); 96 | context.process.send(ProcessMessage::GetLog { 97 | levels: req.0.levels, 98 | callback: tx, 99 | }); 100 | let process_result = rx.recv(); 101 | let result = process_result.ok_or_else(|| RPCError::Internal("Cannot receive process result".to_string()))??; 102 | response(result) 103 | } 104 | 105 | fn agent_get_info(context: &HandlerContext) -> RPCResult { 106 | let (tx, rx) = channel::unbounded(); 107 | context.process.send(ProcessMessage::GetStatus { 108 | callback: tx, 109 | }); 110 | let process_result = rx.recv().ok_or_else(|| RPCError::Internal("Cannot get process result".to_string()))?; 111 | let ProcessGetStatusResult { 112 | status, 113 | port, 114 | commit_hash, 115 | binary_checksum, 116 | } = process_result?; 117 | response(AgentGetInfoResponse { 118 | name: context.name.clone(), 119 | status, 120 | address: port.map(|port| SocketAddr::new(context.codechain_address, port)), 121 | codechain_commit_hash: commit_hash, 122 | codechain_binary_checksum: binary_checksum, 123 | }) 124 | } 125 | 126 | fn codechain_call_rpc(context: &HandlerContext, args: (String, Vec)) -> RPCResult { 127 | let (method, arguments) = args; 128 | let (tx, rx) = channel::unbounded(); 129 | context.process.send(ProcessMessage::CallRPC { 130 | method, 131 | arguments, 132 | callback: tx, 133 | }); 134 | let process_result = rx.recv().ok_or_else(|| RPCError::Internal("Cannot receive process result".to_string()))?; 135 | 136 | let value = match process_result { 137 | Ok(value) => value, 138 | Err(ProcessError::CodeChainRPC(_)) => { 139 | return Err(RPCError::ErrorResponse(ERR_NETWORK_ERROR, "Network Error".to_string(), None)) 140 | } 141 | Err(err) => return Err(err.into()), 142 | }; 143 | response(CodeChainCallRPCResponse { 144 | inner_response: value, 145 | }) 146 | } 147 | 148 | fn hardware_get(context: &HandlerContext) -> RPCResult { 149 | response(context.hardware_service.get()) 150 | } 151 | -------------------------------------------------------------------------------- /src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod api; 2 | pub mod router; 3 | pub mod types; 4 | -------------------------------------------------------------------------------- /src/rpc/router.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use serde::de::Deserialize; 4 | use serde::Serialize; 5 | use serde_json; 6 | use serde_json::Value; 7 | 8 | use super::super::types::HandlerContext; 9 | use super::types::{RPCError, RPCResult}; 10 | 11 | pub trait Route { 12 | fn run(&self, context: &HandlerContext, value: Value) -> RPCResult; 13 | } 14 | 15 | pub struct Router { 16 | table: HashMap<&'static str, Box>, 17 | } 18 | 19 | impl Route for fn(&HandlerContext, Arg) -> RPCResult 20 | where 21 | Res: Serialize, 22 | for<'de> Arg: Deserialize<'de>, 23 | { 24 | fn run(&self, context: &HandlerContext, value: Value) -> RPCResult { 25 | let arg = serde_json::from_value(value)?; 26 | let result = self(context, arg)?; 27 | if let Some(result) = result { 28 | Ok(Some(serde_json::to_value(result)?)) 29 | } else { 30 | Ok(None) 31 | } 32 | } 33 | } 34 | 35 | impl Route for fn(&HandlerContext) -> RPCResult 36 | where 37 | Res: Serialize, 38 | { 39 | fn run(&self, context: &HandlerContext, _value: Value) -> RPCResult { 40 | let result = self(context)?; 41 | if let Some(result) = result { 42 | let value_result = serde_json::to_value(result)?; 43 | Ok(Some(value_result)) 44 | } else { 45 | Ok(None) 46 | } 47 | } 48 | } 49 | 50 | pub enum Error { 51 | MethodNotFound, 52 | RPC(RPCError), 53 | } 54 | 55 | impl Router { 56 | pub fn new() -> Self { 57 | let table: HashMap<&'static str, Box> = HashMap::new(); 58 | Self { 59 | table, 60 | } 61 | } 62 | 63 | pub fn add_route(&mut self, method: &'static str, route: Box) { 64 | self.table.insert(method, route); 65 | } 66 | 67 | pub fn run(&self, context: &HandlerContext, method: &str, arg: Value) -> Result, Error> { 68 | let route = self.table.get(method); 69 | match route { 70 | None => Err(Error::MethodNotFound), 71 | Some(route) => match route.run(context, arg) { 72 | Ok(value) => Ok(value), 73 | Err(err) => Err(Error::RPC(err)), 74 | }, 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/rpc/types.rs: -------------------------------------------------------------------------------- 1 | use jsonrpc_core::types::{Error as JSONRPCError, ErrorCode}; 2 | use serde_json::{Error as SerdeError, Value}; 3 | 4 | use super::super::process::Error as ProcessError; 5 | use std::net::SocketAddr; 6 | 7 | #[derive(Debug, Serialize, Deserialize)] 8 | #[serde(rename_all = "camelCase")] 9 | pub struct ShellStartCodeChainRequest { 10 | pub env: String, 11 | pub args: String, 12 | } 13 | 14 | #[derive(Debug, Deserialize, Serialize)] 15 | #[serde(rename_all = "camelCase")] 16 | #[serde(tag = "type")] 17 | pub enum UpdateCodeChainRequest { 18 | #[serde(rename_all = "camelCase")] 19 | Git { 20 | commit_hash: String, 21 | }, 22 | #[serde(rename_all = "camelCase")] 23 | Binary { 24 | #[serde(rename = "binaryURL")] 25 | binary_url: String, 26 | binary_checksum: String, 27 | }, 28 | } 29 | 30 | #[derive(Debug, Serialize, Deserialize)] 31 | #[serde(rename_all = "camelCase")] 32 | pub struct ShellGetCodeChainLogRequest { 33 | pub levels: Vec, 34 | } 35 | 36 | pub type RPCResult = Result, RPCError>; 37 | 38 | pub enum RPCError { 39 | Process(ProcessError), 40 | Internal(String), 41 | 42 | // Will be returned as error response 43 | ErrorResponse(i64, String, Option), 44 | } 45 | 46 | pub fn response(value: T) -> RPCResult { 47 | Ok(Some(value)) 48 | } 49 | 50 | const ERR_ALREADY_RUNNING: i64 = -10001; 51 | const ERR_ENV_PARSE: i64 = -10002; 52 | const ERR_CODECHAIN_UPDATING: i64 = -10003; 53 | const ERR_PROCESS_INTERNAL: i64 = -32603; 54 | const ERR_CODECHAIN_NOT_RUNNING: i64 = 0; 55 | 56 | pub const ERR_NETWORK_ERROR: i64 = -10001; 57 | 58 | impl RPCError { 59 | pub fn to_jsonrpc_error(&self) -> JSONRPCError { 60 | match self { 61 | RPCError::Internal(str) => Self::create_internal_rpc_error(str), 62 | RPCError::Process(ProcessError::AlreadyRunning) => { 63 | Self::create_rpc_error(ERR_ALREADY_RUNNING, "CodeChain instance is already running") 64 | } 65 | RPCError::Process(ProcessError::EnvParseError) => { 66 | Self::create_rpc_error(ERR_ENV_PARSE, "Invalid env string") 67 | } 68 | RPCError::Process(ProcessError::SubprocessError(err)) => { 69 | Self::create_rpc_error(ERR_PROCESS_INTERNAL, &format!("Process error occured {:?}", err)) 70 | } 71 | RPCError::Process(ProcessError::NotRunning) => { 72 | Self::create_rpc_error(ERR_CODECHAIN_NOT_RUNNING, "CodeChain is not running now") 73 | } 74 | RPCError::Process(ProcessError::Updating) => { 75 | Self::create_rpc_error(ERR_CODECHAIN_UPDATING, "CodeChain is not updating now") 76 | } 77 | RPCError::Process(ProcessError::IO(err)) => { 78 | Self::create_rpc_error(ERR_PROCESS_INTERNAL, &format!("IO error occured {:?}", err)) 79 | } 80 | RPCError::Process(ProcessError::BinaryChecksumMismatch { 81 | expected, 82 | actual, 83 | }) => Self::create_rpc_error( 84 | ERR_PROCESS_INTERNAL, 85 | &format!("Downloaded binary file's sha1sum is {} but it should be {}", actual, expected), 86 | ), 87 | RPCError::Process(ProcessError::CodeChainRPC(err)) => { 88 | Self::create_rpc_error(ERR_PROCESS_INTERNAL, &format!("Sending RPC to ChdeChain failed {}", err)) 89 | } 90 | RPCError::Process(ProcessError::ShellError { 91 | exit_code, 92 | stdout, 93 | stderr, 94 | }) => Self::create_rpc_error( 95 | ERR_PROCESS_INTERNAL, 96 | &format!( 97 | "Shell command has error exit code: {:?}\nstd out: {}\nstd error: {}\n", 98 | exit_code, stdout, stderr 99 | ), 100 | ), 101 | RPCError::Process(ProcessError::Unknown(err)) => { 102 | Self::create_rpc_error(ERR_PROCESS_INTERNAL, &format!("Unknown error from process {}", err)) 103 | } 104 | RPCError::ErrorResponse(code, message, value) => { 105 | Self::create_rpc_error_with_value(*code, message.clone(), value.clone()) 106 | } 107 | } 108 | } 109 | 110 | fn create_rpc_error(code: i64, msg: &str) -> JSONRPCError { 111 | let mut ret = JSONRPCError::new(ErrorCode::ServerError(code)); 112 | ret.message = msg.to_string(); 113 | ret 114 | } 115 | 116 | fn create_rpc_error_with_value(code: i64, msg: String, value: Option) -> JSONRPCError { 117 | let mut ret = JSONRPCError::new(ErrorCode::ServerError(code)); 118 | ret.message = msg; 119 | ret.data = value; 120 | ret 121 | } 122 | 123 | fn create_internal_rpc_error(msg: &str) -> JSONRPCError { 124 | let mut ret = JSONRPCError::new(ErrorCode::InternalError); 125 | ret.data = Some(Value::String(msg.to_string())); 126 | ret 127 | } 128 | } 129 | 130 | impl From for RPCError { 131 | fn from(err: ProcessError) -> Self { 132 | RPCError::Process(err) 133 | } 134 | } 135 | 136 | impl From for RPCError { 137 | fn from(err: SerdeError) -> Self { 138 | RPCError::Internal(format!("Internal error about JSON serialize/deserialize : {:?}", err)) 139 | } 140 | } 141 | 142 | #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] 143 | pub enum NodeStatus { 144 | Starting, 145 | Run, 146 | Stop, 147 | Updating, 148 | Error, 149 | UFO, 150 | } 151 | 152 | #[derive(Debug, Serialize, Deserialize)] 153 | #[serde(rename_all = "camelCase")] 154 | pub struct AgentGetInfoResponse { 155 | pub status: NodeStatus, 156 | pub name: String, 157 | pub address: Option, 158 | pub codechain_commit_hash: String, 159 | pub codechain_binary_checksum: String, 160 | } 161 | 162 | #[derive(Debug, Serialize, Deserialize)] 163 | #[serde(rename_all = "camelCase")] 164 | pub struct CodeChainCallRPCResponse { 165 | pub inner_response: Value, 166 | } 167 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use std::net::IpAddr; 2 | 3 | use crossbeam::Sender; 4 | 5 | use super::hardware_usage::HardwareService; 6 | use super::process::Message as ProcessMessage; 7 | 8 | pub type CommitHash = String; 9 | 10 | pub struct AgentArgs<'a> { 11 | pub codechain_dir: &'a str, 12 | pub log_file_path: &'a str, 13 | pub hub_url: &'a str, 14 | pub codechain_address: IpAddr, 15 | pub name: &'a str, 16 | } 17 | 18 | pub struct HandlerContext { 19 | pub process: Sender, 20 | pub codechain_address: IpAddr, 21 | pub name: String, 22 | pub hardware_service: HardwareService, 23 | } 24 | --------------------------------------------------------------------------------