diff --git a/Cargo.lock b/Cargo.lock
index db9dde0..353d1a0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,12 +18,43 @@ version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6"
 
+[[package]]
+name = "addr2line"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+dependencies = [
+ "gimli",
+]
+
 [[package]]
 name = "adler"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
+[[package]]
+name = "aes"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfe0133578c0986e1fe3dfcd4af1cc5b2dd6c3dbf534d69916ce16a2701d40ba"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom 0.2.7",
+ "once_cell",
+ "version_check",
+]
+
 [[package]]
 name = "ahash"
 version = "0.8.0"
@@ -54,6 +85,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "anyhow"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
+
 [[package]]
 name = "arboard"
 version = "2.1.1"
@@ -89,6 +126,130 @@ version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
 
+[[package]]
+name = "arti-client"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e5b8d84142e82a79883babb3dfd59d1df38b9f144e8bd0b395fec7187d5ad0d"
+dependencies = [
+ "cfg-if",
+ "derive_builder_fork_arti",
+ "derive_more",
+ "directories",
+ "educe",
+ "fs-mistrust",
+ "futures",
+ "humantime-serde",
+ "libc",
+ "pin-project",
+ "postage",
+ "safelog",
+ "serde",
+ "thiserror",
+ "tor-basic-utils",
+ "tor-cell",
+ "tor-chanmgr",
+ "tor-checkable",
+ "tor-circmgr",
+ "tor-config",
+ "tor-dirmgr",
+ "tor-error",
+ "tor-guardmgr",
+ "tor-llcrypto",
+ "tor-netdir",
+ "tor-netdoc",
+ "tor-persist",
+ "tor-proto",
+ "tor-rtcompat",
+ "tracing",
+]
+
+[[package]]
+name = "arti-hyper"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed115fb88a35c0c7a2ffd82d772446c4cddf57cfdedb6fb78899c367b552186"
+dependencies = [
+ "anyhow",
+ "arti-client",
+ "educe",
+ "hyper",
+ "pin-project",
+ "thiserror",
+ "tls-api",
+ "tls-api-native-tls",
+ "tokio",
+ "tor-error",
+ "tor-rtcompat",
+]
+
+[[package]]
+name = "async-compression"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
+dependencies = [
+ "flate2",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "pin-project-lite",
+ "xz2",
+ "zstd",
+ "zstd-safe",
+]
+
+[[package]]
+name = "async-native-tls"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d57d4cec3c647232e1094dc013546c0b33ce785d8aeb251e1f20dfaf8a9a13fe"
+dependencies = [
+ "futures-util",
+ "native-tls",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async_executors"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0b2463773401e1f684136f9cdb956cf611f22172472cf3f049e72123f59e359"
+dependencies = [
+ "blanket",
+ "futures-core",
+ "futures-task",
+ "futures-util",
+ "pin-project",
+ "rustc_version",
+ "tokio",
+]
+
+[[package]]
+name = "asynchronous-codec"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690"
+dependencies = [
+ "bytes",
+ "futures-sink",
+ "futures-util",
+ "memchr",
+ "pin-project-lite",
+]
+
 [[package]]
 name = "atomic"
 version = "0.5.1"
@@ -121,6 +282,21 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
+[[package]]
+name = "backtrace"
+version = "0.3.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide 0.5.4",
+ "object",
+ "rustc-demangle",
+]
+
 [[package]]
 name = "base58-monero"
 version = "1.0.0"
@@ -136,6 +312,12 @@ version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
 
+[[package]]
+name = "base64ct"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
+
 [[package]]
 name = "bit_field"
 version = "0.10.1"
@@ -148,12 +330,32 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
+[[package]]
+name = "blanket"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b04ce3d2372d05d1ef4ea3fdf427da6ae3c17ca06d688a107b5344836276bc3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "block"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
 
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "block-buffer"
 version = "0.10.3"
@@ -163,6 +365,12 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "bounded-vec-deque"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2225b558afc76c596898f5f1b3fc35cfce0eb1b13635cbd7d1b2a7177dc10ccd"
+
 [[package]]
 name = "bumpalo"
 version = "3.11.0"
@@ -214,11 +422,20 @@ dependencies = [
  "vec_map",
 ]
 
+[[package]]
+name = "caret"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ceea694ffdf0118d2df95ace6fd9edfc6d27f88408d0d73b390f2d9e5699b3f2"
+
 [[package]]
 name = "cc"
 version = "1.0.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+dependencies = [
+ "jobserver",
+]
 
 [[package]]
 name = "cesu8"
@@ -251,11 +468,22 @@ dependencies = [
  "js-sys",
  "num-integer",
  "num-traits",
- "time",
+ "time 0.1.44",
  "wasm-bindgen",
  "winapi",
 ]
 
+[[package]]
+name = "cipher"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
+dependencies = [
+ "crypto-common",
+ "inout",
+ "zeroize",
+]
+
 [[package]]
 name = "clipboard-win"
 version = "4.4.2"
@@ -276,6 +504,18 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "coarsetime"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "454038500439e141804c655b4cd1bc6a70bcb95cd2bc9463af5661b6956f0e46"
+dependencies = [
+ "libc",
+ "once_cell",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "cocoa"
 version = "0.24.0"
@@ -323,6 +563,32 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "config"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11f1667b8320afa80d69d8bbe40830df2c8a06003d86f73d8e003b2c48df416d"
+dependencies = [
+ "async-trait",
+ "lazy_static",
+ "nom",
+ "pathdiff",
+ "serde",
+ "toml",
+]
+
+[[package]]
+name = "const-oid"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
+
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
 [[package]]
 name = "core-foundation"
 version = "0.9.3"
@@ -428,6 +694,16 @@ dependencies = [
  "scopeguard",
 ]
 
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
 [[package]]
 name = "crossbeam-utils"
 version = "0.8.12"
@@ -466,6 +742,16 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
+[[package]]
+name = "crypto-bigint"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
+dependencies = [
+ "generic-array",
+ "subtle",
+]
+
 [[package]]
 name = "crypto-common"
 version = "0.1.6"
@@ -476,6 +762,15 @@ dependencies = [
  "typenum",
 ]
 
+[[package]]
+name = "ctr"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
+dependencies = [
+ "cipher",
+]
+
 [[package]]
 name = "cty"
 version = "0.2.2"
@@ -484,9 +779,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
 
 [[package]]
 name = "curve25519-dalek"
-version = "3.2.1"
+version = "3.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
+checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
 dependencies = [
  "byteorder",
  "digest 0.9.0",
@@ -501,8 +796,18 @@ version = "0.13.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
 dependencies = [
- "darling_core",
- "darling_macro",
+ "darling_core 0.13.4",
+ "darling_macro 0.13.4",
+]
+
+[[package]]
+name = "darling"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
+dependencies = [
+ "darling_core 0.14.1",
+ "darling_macro 0.14.1",
 ]
 
 [[package]]
@@ -519,17 +824,97 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "darling_core"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn",
+]
+
 [[package]]
 name = "darling_macro"
 version = "0.13.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
 dependencies = [
- "darling_core",
+ "darling_core 0.13.4",
  "quote",
  "syn",
 ]
 
+[[package]]
+name = "darling_macro"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
+dependencies = [
+ "darling_core 0.14.1",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "der"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
+dependencies = [
+ "const-oid",
+ "crypto-bigint",
+ "pem-rfc7468",
+]
+
+[[package]]
+name = "derive_builder_core_fork_arti"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24c1b715c79be6328caa9a5e1a387a196ea503740f0722ec3dd8f67a9e72314d"
+dependencies = [
+ "darling 0.14.1",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "derive_builder_fork_arti"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3eae24d595f4d0ecc90a9a5a6d11c2bd8dafe2375ec4a1ec63250e5ade7d228"
+dependencies = [
+ "derive_builder_macro_fork_arti",
+]
+
+[[package]]
+name = "derive_builder_macro_fork_arti"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69887769a2489cd946bf782eb2b1bb2cb7bc88551440c94a765d4f040c08ebf3"
+dependencies = [
+ "derive_builder_core_fork_arti",
+ "syn",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn",
+]
+
 [[package]]
 name = "digest"
 version = "0.9.0"
@@ -545,8 +930,18 @@ version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
 dependencies = [
- "block-buffer",
+ "block-buffer 0.10.3",
  "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "directories"
+version = "4.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
+dependencies = [
+ "dirs-sys",
 ]
 
 [[package]]
@@ -575,6 +970,17 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
 
+[[package]]
+name = "displaydoc"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "dlib"
 version = "0.5.0"
@@ -604,6 +1010,48 @@ dependencies = [
  "wio",
 ]
 
+[[package]]
+name = "dyn-clone"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2"
+
+[[package]]
+name = "ed25519"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
+dependencies = [
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
+dependencies = [
+ "curve25519-dalek",
+ "ed25519",
+ "merlin",
+ "rand 0.7.3",
+ "serde",
+ "sha2 0.9.9",
+ "zeroize",
+]
+
+[[package]]
+name = "educe"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c07b7cc9cd8c08d10db74fca3b20949b9b6199725c04a0cce6d543496098fcac"
+dependencies = [
+ "enum-ordinalize",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "eframe"
 version = "0.19.0"
@@ -632,7 +1080,7 @@ version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc9fcd393c3daaaf5909008a1d948319d538b79c51871e4df0993260260a94e4"
 dependencies = [
- "ahash",
+ "ahash 0.8.0",
  "epaint",
  "nohash-hasher",
  "tracing",
@@ -702,6 +1150,33 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "enum-ordinalize"
+version = "3.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2170fc0efee383079a8bdd05d6ea2a184d2a0f07a1c1dcabdb2fd5e9f24bc36c"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.5.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
+dependencies = [
+ "atty",
+ "humantime 1.3.0",
+ "log",
+ "regex",
+ "termcolor",
+]
+
 [[package]]
 name = "env_logger"
 version = "0.9.1"
@@ -709,7 +1184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272"
 dependencies = [
  "atty",
- "humantime",
+ "humantime 2.1.0",
  "log",
  "regex",
  "termcolor",
@@ -722,7 +1197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5ba04741be7f6602b1a1b28f1082cce45948a7032961c52814f8946b28493300"
 dependencies = [
  "ab_glyph",
- "ahash",
+ "ahash 0.8.0",
  "atomic_refcell",
  "bytemuck",
  "emath",
@@ -740,6 +1215,12 @@ dependencies = [
  "str-buf",
 ]
 
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
 [[package]]
 name = "expat-sys"
 version = "2.1.6"
@@ -765,6 +1246,18 @@ dependencies = [
  "threadpool",
 ]
 
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
 [[package]]
 name = "fastrand"
 version = "1.8.0"
@@ -787,6 +1280,18 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "filetime"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "windows-sys 0.42.0",
+]
+
 [[package]]
 name = "fixed-hash"
 version = "0.7.0"
@@ -794,7 +1299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c"
 dependencies = [
  "byteorder",
- "rand",
+ "rand 0.8.5",
  "rustc-hex",
  "static_assertions",
 ]
@@ -809,6 +1314,12 @@ dependencies = [
  "miniz_oxide 0.5.4",
 ]
 
+[[package]]
+name = "fluid-let"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "749cff877dc1af878a0b31a41dd221a753634401ea0ef2f87b62d3171522485a"
+
 [[package]]
 name = "flume"
 version = "0.10.14"
@@ -819,7 +1330,7 @@ dependencies = [
  "futures-sink",
  "nanorand",
  "pin-project",
- "spin",
+ "spin 0.9.4",
 ]
 
 [[package]]
@@ -902,46 +1413,115 @@ dependencies = [
 ]
 
 [[package]]
-name = "futures-channel"
-version = "0.3.24"
+name = "fs-mistrust"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
+checksum = "a7c94d63028b6272bcd574ea1cd7764f544bb79c58337bcdbedb0a58e8a331fe"
+dependencies = [
+ "derive_builder_fork_arti",
+ "derive_more",
+ "dirs",
+ "educe",
+ "libc",
+ "once_cell",
+ "serde",
+ "thiserror",
+ "users",
+ "walkdir",
+]
+
+[[package]]
+name = "fslock"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
 dependencies = [
  "futures-core",
+ "futures-sink",
 ]
 
 [[package]]
 name = "futures-core"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
+checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
 
 [[package]]
 name = "futures-io"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
+checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
+checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
 
 [[package]]
 name = "futures-task"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
+checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
 
 [[package]]
 name = "futures-util"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
+checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
 dependencies = [
+ "futures-channel",
  "futures-core",
  "futures-io",
+ "futures-macro",
+ "futures-sink",
  "futures-task",
  "memchr",
  "pin-project-lite",
@@ -1003,6 +1583,12 @@ dependencies = [
  "weezl",
 ]
 
+[[package]]
+name = "gimli"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+
 [[package]]
 name = "gl_generator"
 version = "0.14.0"
@@ -1095,34 +1681,48 @@ dependencies = [
 name = "gupax"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
+ "arti-client",
+ "arti-hyper",
+ "bytes",
  "chrono",
  "dirs",
  "eframe",
  "egui",
  "egui_extras",
- "env_logger",
+ "env_logger 0.9.1",
  "figment",
+ "flate2",
  "hex-literal",
+ "hyper",
+ "hyper-tls",
  "image",
  "log",
  "monero",
  "num-format",
  "num_cpus",
  "openssl",
- "rand",
+ "rand 0.8.5",
  "regex",
  "reqwest",
  "serde",
  "serde_derive",
- "sha2",
+ "serde_json",
+ "sha2 0.10.6",
+ "tar",
+ "tls-api",
+ "tls-api-native-tls",
+ "tokio",
  "toml",
+ "tor-rtcompat",
+ "walkdir",
 ]
 
 [[package]]
 name = "h2"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be"
+checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
 dependencies = [
  "bytes",
  "fnv",
@@ -1151,6 +1751,18 @@ name = "hashbrown"
 version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash 0.7.6",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa"
+dependencies = [
+ "hashbrown",
+]
 
 [[package]]
 name = "heck"
@@ -1161,6 +1773,12 @@ dependencies = [
  "unicode-segmentation",
 ]
 
+[[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
 [[package]]
 name = "hermit-abi"
 version = "0.1.19"
@@ -1182,6 +1800,24 @@ version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
 
+[[package]]
+name = "hkdf"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.5",
+]
+
 [[package]]
 name = "http"
 version = "0.2.8"
@@ -1216,12 +1852,31 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
 
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error",
+]
+
 [[package]]
 name = "humantime"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
+[[package]]
+name = "humantime-serde"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c"
+dependencies = [
+ "humantime 2.1.0",
+ "serde",
+]
+
 [[package]]
 name = "hyper"
 version = "0.14.20"
@@ -1317,6 +1972,15 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "instant"
 version = "0.1.12"
@@ -1335,6 +1999,15 @@ version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
 
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
 version = "1.0.4"
@@ -1361,6 +2034,15 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
 
+[[package]]
+name = "jobserver"
+version = "0.1.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "jpeg-decoder"
 version = "0.2.6"
@@ -1379,6 +2061,12 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "keccak"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838"
+
 [[package]]
 name = "khronos_api"
 version = "3.1.0"
@@ -1390,6 +2078,9 @@ name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
 
 [[package]]
 name = "lebe"
@@ -1413,6 +2104,22 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "libm"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
+
+[[package]]
+name = "libsqlite3-sys"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35"
+dependencies = [
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "lock_api"
 version = "0.4.9"
@@ -1432,6 +2139,17 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "lzma-sys"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e06754c4acf47d49c727d5665ca9fb828851cda315ed3bd51edd148ef78a8772"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
 [[package]]
 name = "malloc_buf"
 version = "0.0.6"
@@ -1465,6 +2183,18 @@ dependencies = [
  "autocfg",
 ]
 
+[[package]]
+name = "merlin"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42"
+dependencies = [
+ "byteorder",
+ "keccak",
+ "rand_core 0.5.1",
+ "zeroize",
+]
+
 [[package]]
 name = "mime"
 version = "0.3.16"
@@ -1504,7 +2234,7 @@ dependencies = [
  "libc",
  "log",
  "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys",
+ "windows-sys 0.36.1",
 ]
 
 [[package]]
@@ -1620,7 +2350,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c"
 dependencies = [
- "darling",
+ "darling 0.13.4",
  "proc-macro-crate",
  "proc-macro2",
  "quote",
@@ -1686,6 +2416,34 @@ dependencies = [
  "minimal-lexical",
 ]
 
+[[package]]
+name = "num-bigint"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint-dig"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011"
+dependencies = [
+ "byteorder",
+ "lazy_static",
+ "libm",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "rand 0.8.5",
+ "smallvec",
+ "zeroize",
+]
+
 [[package]]
 name = "num-format"
 version = "0.4.3"
@@ -1706,6 +2464,17 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "num-iter"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
 [[package]]
 name = "num-rational"
 version = "0.4.1"
@@ -1724,6 +2493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
 dependencies = [
  "autocfg",
+ "libm",
 ]
 
 [[package]]
@@ -1757,6 +2527,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "num_threads"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "objc"
 version = "0.2.7"
@@ -1786,12 +2565,27 @@ dependencies = [
  "objc",
 ]
 
+[[package]]
+name = "object"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
 
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
 [[package]]
 name = "openssl"
 version = "0.10.42"
@@ -1885,7 +2679,39 @@ dependencies = [
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys",
+ "windows-sys 0.36.1",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "pem"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
+dependencies = [
+ "base64",
+ "once_cell",
+ "regex",
+]
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30"
+dependencies = [
+ "base64ct",
 ]
 
 [[package]]
@@ -1894,6 +2720,50 @@ version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
+[[package]]
+name = "phf"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
+dependencies = [
+ "phf_shared",
+ "rand 0.8.5",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
+dependencies = [
+ "siphasher",
+]
+
 [[package]]
 name = "pin-project"
 version = "1.0.12"
@@ -1926,6 +2796,28 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
+[[package]]
+name = "pkcs1"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320"
+dependencies = [
+ "der",
+ "pkcs8",
+ "zeroize",
+]
+
+[[package]]
+name = "pkcs8"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
+dependencies = [
+ "der",
+ "spki",
+ "zeroize",
+]
+
 [[package]]
 name = "pkg-config"
 version = "0.3.25"
@@ -1944,6 +2836,21 @@ dependencies = [
  "miniz_oxide 0.5.4",
 ]
 
+[[package]]
+name = "postage"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af3fb618632874fb76937c2361a7f22afd393c982a2165595407edc75b06d3c1"
+dependencies = [
+ "atomic",
+ "crossbeam-queue",
+ "futures",
+ "parking_lot",
+ "pin-project",
+ "static_assertions",
+ "thiserror",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.16"
@@ -1961,6 +2868,12 @@ dependencies = [
  "toml",
 ]
 
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.46"
@@ -1970,6 +2883,12 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
 [[package]]
 name = "quote"
 version = "1.0.21"
@@ -1979,6 +2898,19 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc",
+]
+
 [[package]]
 name = "rand"
 version = "0.8.5"
@@ -1986,10 +2918,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
 ]
 
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
+]
+
 [[package]]
 name = "rand_chacha"
 version = "0.3.1"
@@ -2018,6 +2960,15 @@ dependencies = [
  "getrandom 0.2.7",
 ]
 
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
 [[package]]
 name = "raw-window-handle"
 version = "0.4.3"
@@ -2143,12 +3094,95 @@ dependencies = [
  "winreg",
 ]
 
+[[package]]
+name = "retain_mut"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0"
+
+[[package]]
+name = "retry-error"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90987092c28e12b9cfcea38be09f931b7cfcfe41429f2d0971f2cd57903d5d12"
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin 0.5.2",
+ "untrusted 0.7.1",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
+name = "rsa"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b"
+dependencies = [
+ "byteorder",
+ "digest 0.10.5",
+ "num-bigint-dig",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "pkcs1",
+ "pkcs8",
+ "rand_core 0.6.4",
+ "smallvec",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rusqlite"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a"
+dependencies = [
+ "bitflags",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
+ "libsqlite3-sys",
+ "smallvec",
+ "time 0.3.16",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
 [[package]]
 name = "rustc-hex"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
 
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
+
 [[package]]
 name = "ryu"
 version = "1.0.11"
@@ -2164,6 +3198,17 @@ dependencies = [
  "bytemuck",
 ]
 
+[[package]]
+name = "safelog"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2db2b401598634604067134dcf33906d01bdc922bb802b85b3cb33e3a1a8cd29"
+dependencies = [
+ "educe",
+ "fluid-let",
+ "thiserror",
+]
+
 [[package]]
 name = "same-file"
 version = "1.0.6"
@@ -2173,6 +3218,16 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "sanitize-filename"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c"
+dependencies = [
+ "lazy_static",
+ "regex",
+]
+
 [[package]]
 name = "schannel"
 version = "0.1.20"
@@ -2180,7 +3235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
 dependencies = [
  "lazy_static",
- "windows-sys",
+ "windows-sys 0.36.1",
 ]
 
 [[package]]
@@ -2219,7 +3274,7 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6b5e421024b5e5edfbaa8e60ecf90bda9dbffc602dbb230e6028763f85f0c68c"
 dependencies = [
- "heck",
+ "heck 0.3.3",
  "proc-macro2",
  "quote",
  "syn",
@@ -2248,11 +3303,20 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "semver"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+
 [[package]]
 name = "serde"
 version = "1.0.145"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+dependencies = [
+ "serde_derive",
+]
 
 [[package]]
 name = "serde_derive"
@@ -2265,6 +3329,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "serde_ignored"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82b3da7eedd967647a866f67829d1c79d184d7c4521126e9cc2c46a9585c6d21"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "serde_json"
 version = "1.0.86"
@@ -2288,6 +3361,28 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_with"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff"
+dependencies = [
+ "serde",
+ "serde_with_macros",
+]
+
+[[package]]
+name = "serde_with_macros"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
+dependencies = [
+ "darling 0.13.4",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "servo-fontconfig"
 version = "0.5.1"
@@ -2309,6 +3404,30 @@ dependencies = [
  "pkg-config",
 ]
 
+[[package]]
+name = "sha-1"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.5",
+]
+
+[[package]]
+name = "sha2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
 [[package]]
 name = "sha2"
 version = "0.10.6"
@@ -2320,6 +3439,16 @@ dependencies = [
  "digest 0.10.5",
 ]
 
+[[package]]
+name = "sha3"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9"
+dependencies = [
+ "digest 0.10.5",
+ "keccak",
+]
+
 [[package]]
 name = "shared_library"
 version = "0.1.9"
@@ -2330,6 +3459,48 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "shellexpand"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
+dependencies = [
+ "dirs",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "signature"
+version = "1.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+
+[[package]]
+name = "simple_asn1"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "thiserror",
+ "time 0.3.16",
+]
+
+[[package]]
+name = "siphasher"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+
 [[package]]
 name = "slab"
 version = "0.4.7"
@@ -2393,6 +3564,12 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
 [[package]]
 name = "spin"
 version = "0.9.4"
@@ -2402,6 +3579,16 @@ dependencies = [
  "lock_api",
 ]
 
+[[package]]
+name = "spki"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
 [[package]]
 name = "static_assertions"
 version = "1.1.0"
@@ -2420,6 +3607,28 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
+[[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck 0.4.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
 [[package]]
 name = "subtle"
 version = "2.4.1"
@@ -2437,6 +3646,29 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tar"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
 [[package]]
 name = "tempfile"
 version = "3.3.0"
@@ -2460,6 +3692,17 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "test-cert-gen"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "345f92b7cac59507cdaba298c5493f7c40e2063d31f6fc621105183344d5d50a"
+dependencies = [
+ "once_cell",
+ "pem",
+ "tempfile",
+]
+
 [[package]]
 name = "thiserror"
 version = "1.0.37"
@@ -2511,6 +3754,35 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "time"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca"
+dependencies = [
+ "itoa",
+ "libc",
+ "num_threads",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+
+[[package]]
+name = "time-macros"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b"
+dependencies = [
+ "time-core",
+]
+
 [[package]]
 name = "tiny-keccak"
 version = "2.0.2"
@@ -2545,6 +3817,15 @@ dependencies = [
  "bytemuck",
 ]
 
+[[package]]
+name = "tinystr"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dfb77d2490072fb5616d67686f55481b3d97701e383e208a7225843eba1aae6"
+dependencies = [
+ "displaydoc",
+]
+
 [[package]]
 name = "tinyvec"
 version = "1.6.0"
@@ -2560,6 +3841,53 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
+[[package]]
+name = "tls-api"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66d1b3dfb0a60da3e8a130c9f2432063d9979928a05c2b2cdcfc9fd05e4f53a3"
+dependencies = [
+ "anyhow",
+ "log",
+ "pem",
+ "tempfile",
+ "thiserror",
+ "tokio",
+ "void",
+ "webpki",
+]
+
+[[package]]
+name = "tls-api-native-tls"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b935bda2458120a5d2cea542013796fcf13937566580027f6a08f42a52206f7"
+dependencies = [
+ "anyhow",
+ "native-tls",
+ "thiserror",
+ "tls-api",
+ "tls-api-test",
+ "tokio",
+]
+
+[[package]]
+name = "tls-api-test"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9df107843d725428d76bb159040fbae6d1524dcf25d5b24c56daa6b37ce9dbb5"
+dependencies = [
+ "anyhow",
+ "env_logger 0.5.13",
+ "log",
+ "pem",
+ "test-cert-gen",
+ "tls-api",
+ "tokio",
+ "untrusted 0.6.2",
+ "webpki",
+]
+
 [[package]]
 name = "tokio"
 version = "1.21.2"
@@ -2572,11 +3900,25 @@ dependencies = [
  "memchr",
  "mio",
  "num_cpus",
+ "parking_lot",
  "pin-project-lite",
+ "signal-hook-registry",
  "socket2",
+ "tokio-macros",
  "winapi",
 ]
 
+[[package]]
+name = "tokio-macros"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "tokio-native-tls"
 version = "0.3.0"
@@ -2595,6 +3937,7 @@ checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
 dependencies = [
  "bytes",
  "futures-core",
+ "futures-io",
  "futures-sink",
  "pin-project-lite",
  "tokio",
@@ -2610,6 +3953,534 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "tor-basic-utils"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc47159011c88902a21399f35e898b748295b9e0eb39f7012d29eb123432dfe2"
+dependencies = [
+ "futures",
+ "hex",
+ "libc",
+ "pin-project",
+ "postage",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
+ "thiserror",
+ "void",
+]
+
+[[package]]
+name = "tor-bytes"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a212a87f32d6703b08276ce59e26b4b18e14b4e45bbd08d5fcacd93ffca8841"
+dependencies = [
+ "arrayref",
+ "bytes",
+ "digest 0.10.5",
+ "educe",
+ "generic-array",
+ "getrandom 0.2.7",
+ "signature",
+ "thiserror",
+ "tor-error",
+ "tor-llcrypto",
+ "zeroize",
+]
+
+[[package]]
+name = "tor-cell"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc36db623585c248867fa530caa5d8df4f7bccedaf85d84a3e911a662de8742c"
+dependencies = [
+ "arrayref",
+ "bitflags",
+ "bytes",
+ "caret",
+ "educe",
+ "rand 0.8.5",
+ "thiserror",
+ "tor-basic-utils",
+ "tor-bytes",
+ "tor-cert",
+ "tor-error",
+ "tor-linkspec",
+ "tor-llcrypto",
+ "tor-units",
+]
+
+[[package]]
+name = "tor-cert"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cfbe2cd71c0753a039f7e212d81fd69ac93903ba7f0bafd3db6d5e8b8607022"
+dependencies = [
+ "caret",
+ "digest 0.10.5",
+ "signature",
+ "thiserror",
+ "tor-bytes",
+ "tor-checkable",
+ "tor-llcrypto",
+]
+
+[[package]]
+name = "tor-chanmgr"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "394323f8b8a125a45ccc00f112ef0a78c9a8615818d5e60481933b21a4776174"
+dependencies = [
+ "async-trait",
+ "derive_builder_fork_arti",
+ "derive_more",
+ "educe",
+ "futures",
+ "postage",
+ "rand 0.8.5",
+ "safelog",
+ "serde",
+ "thiserror",
+ "tor-basic-utils",
+ "tor-cell",
+ "tor-config",
+ "tor-error",
+ "tor-linkspec",
+ "tor-llcrypto",
+ "tor-netdir",
+ "tor-proto",
+ "tor-rtcompat",
+ "tor-units",
+ "tracing",
+ "void",
+]
+
+[[package]]
+name = "tor-checkable"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e00fd9e57905f211c201274ea8eb096db8301e72d0900e93917b14e2ecd1370a"
+dependencies = [
+ "humantime 2.1.0",
+ "signature",
+ "thiserror",
+ "tor-llcrypto",
+]
+
+[[package]]
+name = "tor-circmgr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5f74f2b3c3343e31e53fe29c649f65f72a3837762de52834908a0ba4caf6e04"
+dependencies = [
+ "async-trait",
+ "bounded-vec-deque",
+ "derive_builder_fork_arti",
+ "downcast-rs",
+ "dyn-clone",
+ "educe",
+ "futures",
+ "humantime-serde",
+ "itertools",
+ "once_cell",
+ "pin-project",
+ "rand 0.8.5",
+ "retry-error",
+ "safelog",
+ "serde",
+ "static_assertions",
+ "thiserror",
+ "tor-basic-utils",
+ "tor-chanmgr",
+ "tor-config",
+ "tor-error",
+ "tor-guardmgr",
+ "tor-linkspec",
+ "tor-netdir",
+ "tor-netdoc",
+ "tor-persist",
+ "tor-proto",
+ "tor-rtcompat",
+ "tracing",
+ "weak-table",
+]
+
+[[package]]
+name = "tor-config"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06e709eaebd399c825b31450ba43a49c438e9cf885fc4c5f5fd0810f5b02e6e9"
+dependencies = [
+ "config",
+ "derive_builder_fork_arti",
+ "directories",
+ "educe",
+ "either",
+ "fs-mistrust",
+ "itertools",
+ "once_cell",
+ "paste",
+ "regex",
+ "serde",
+ "serde_ignored",
+ "shellexpand",
+ "strum",
+ "thiserror",
+ "toml",
+ "tor-basic-utils",
+ "tor-error",
+ "tracing",
+]
+
+[[package]]
+name = "tor-consdiff"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1105ea5a5e348f0e2d81cd1f60c1fdbe84b4f9f15f67d8917bca2911a72878b7"
+dependencies = [
+ "digest 0.10.5",
+ "hex",
+ "thiserror",
+ "tor-llcrypto",
+]
+
+[[package]]
+name = "tor-dirclient"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "070357a78f37eaf8b0305b85552ead97ce16f4261fe37db6cfff52a3a1d93c94"
+dependencies = [
+ "async-compression",
+ "base64",
+ "derive_more",
+ "futures",
+ "hex",
+ "http",
+ "httparse",
+ "httpdate",
+ "itertools",
+ "memchr",
+ "thiserror",
+ "tor-circmgr",
+ "tor-error",
+ "tor-linkspec",
+ "tor-llcrypto",
+ "tor-netdoc",
+ "tor-proto",
+ "tor-rtcompat",
+ "tracing",
+]
+
+[[package]]
+name = "tor-dirmgr"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cf017cfb4fcd8df9cd83ff1c523b10c9ede31a836b484064d36db8220b8006a"
+dependencies = [
+ "async-trait",
+ "base64",
+ "derive_builder_fork_arti",
+ "derive_more",
+ "digest 0.10.5",
+ "educe",
+ "event-listener",
+ "fs-mistrust",
+ "fslock",
+ "futures",
+ "hex",
+ "humantime-serde",
+ "itertools",
+ "memmap2",
+ "once_cell",
+ "postage",
+ "rand 0.8.5",
+ "retry-error",
+ "rusqlite",
+ "scopeguard",
+ "serde",
+ "signature",
+ "thiserror",
+ "time 0.3.16",
+ "tor-basic-utils",
+ "tor-checkable",
+ "tor-circmgr",
+ "tor-config",
+ "tor-consdiff",
+ "tor-dirclient",
+ "tor-error",
+ "tor-guardmgr",
+ "tor-llcrypto",
+ "tor-netdir",
+ "tor-netdoc",
+ "tor-rtcompat",
+ "tracing",
+]
+
+[[package]]
+name = "tor-error"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1703f7d6ddac09f14556ad7fc8de36bd8077dbabc5a779485d335899c31a282"
+dependencies = [
+ "backtrace",
+ "derive_more",
+ "futures",
+ "once_cell",
+ "strum",
+ "thiserror",
+]
+
+[[package]]
+name = "tor-guardmgr"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b376555a9ae5d5f0c41a2c77375ab2b0603da6dbcfa8e85f7161fe3b7c8964f"
+dependencies = [
+ "base64",
+ "derive_builder_fork_arti",
+ "derive_more",
+ "educe",
+ "futures",
+ "humantime 2.1.0",
+ "humantime-serde",
+ "itertools",
+ "pin-project",
+ "postage",
+ "rand 0.8.5",
+ "retain_mut",
+ "serde",
+ "thiserror",
+ "tor-basic-utils",
+ "tor-config",
+ "tor-error",
+ "tor-linkspec",
+ "tor-llcrypto",
+ "tor-netdir",
+ "tor-netdoc",
+ "tor-persist",
+ "tor-proto",
+ "tor-rtcompat",
+ "tor-units",
+ "tracing",
+]
+
+[[package]]
+name = "tor-linkspec"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "deeca8885912c4ed3d0d74e3c13cc23961dd7a63ecd2bc06a6b907da601ae8c7"
+dependencies = [
+ "base64ct",
+ "cfg-if",
+ "derive_more",
+ "educe",
+ "hex",
+ "serde",
+ "strum",
+ "thiserror",
+ "tor-bytes",
+ "tor-llcrypto",
+ "tor-protover",
+]
+
+[[package]]
+name = "tor-llcrypto"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97db0224b69d341e34cefea7e58f63a42ed3def4e39182a68b007a4839294800"
+dependencies = [
+ "aes",
+ "arrayref",
+ "base64",
+ "ctr",
+ "curve25519-dalek",
+ "digest 0.10.5",
+ "ed25519-dalek",
+ "getrandom 0.2.7",
+ "hex",
+ "rand_core 0.5.1",
+ "rand_core 0.6.4",
+ "rsa",
+ "serde",
+ "sha-1",
+ "sha2 0.10.6",
+ "sha3",
+ "signature",
+ "simple_asn1",
+ "subtle",
+ "thiserror",
+ "x25519-dalek",
+ "zeroize",
+]
+
+[[package]]
+name = "tor-netdir"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eadefbdaee1a935a2e628b6c05c690f5edf93412edaf1ccffa36d65905cad257"
+dependencies = [
+ "bitflags",
+ "derive_builder_fork_arti",
+ "derive_more",
+ "futures",
+ "rand 0.8.5",
+ "serde",
+ "signature",
+ "static_assertions",
+ "thiserror",
+ "tor-checkable",
+ "tor-config",
+ "tor-error",
+ "tor-linkspec",
+ "tor-llcrypto",
+ "tor-netdoc",
+ "tor-protover",
+ "tor-units",
+ "tracing",
+]
+
+[[package]]
+name = "tor-netdoc"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "814aae0fcc76adee10f7ffaf66b41b731c77904da051df206b9bb501271bcef9"
+dependencies = [
+ "base64ct",
+ "bitflags",
+ "derive_more",
+ "digest 0.10.5",
+ "educe",
+ "hex",
+ "once_cell",
+ "phf",
+ "serde",
+ "serde_with",
+ "signature",
+ "thiserror",
+ "time 0.3.16",
+ "tinystr",
+ "tor-bytes",
+ "tor-cert",
+ "tor-checkable",
+ "tor-error",
+ "tor-llcrypto",
+ "tor-protover",
+ "weak-table",
+]
+
+[[package]]
+name = "tor-persist"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57e2bc7d14217a4d277138ef2ff4b7b2d7c0fec53335aa86f4b0a4b1e47cd8c2"
+dependencies = [
+ "derive_more",
+ "fs-mistrust",
+ "fslock",
+ "sanitize-filename",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "tor-error",
+ "tracing",
+]
+
+[[package]]
+name = "tor-proto"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb3403655013da99bb7b83e3894158e82f8ec4f609dfef873787d97f75ff956"
+dependencies = [
+ "arrayref",
+ "asynchronous-codec",
+ "bytes",
+ "cipher",
+ "coarsetime",
+ "derive_builder_fork_arti",
+ "digest 0.10.5",
+ "educe",
+ "futures",
+ "generic-array",
+ "hkdf",
+ "hmac",
+ "pin-project",
+ "rand 0.8.5",
+ "rand_core 0.6.4",
+ "subtle",
+ "thiserror",
+ "tokio",
+ "tokio-util",
+ "tor-basic-utils",
+ "tor-bytes",
+ "tor-cell",
+ "tor-cert",
+ "tor-checkable",
+ "tor-config",
+ "tor-error",
+ "tor-linkspec",
+ "tor-llcrypto",
+ "tor-protover",
+ "tor-rtcompat",
+ "tor-rtmock",
+ "tor-units",
+ "tracing",
+ "typenum",
+ "zeroize",
+]
+
+[[package]]
+name = "tor-protover"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2249891a8cd7c6b29c7dee333ae8df4225b28958ab385a84f75c22c0dfc1819"
+dependencies = [
+ "caret",
+ "thiserror",
+]
+
+[[package]]
+name = "tor-rtcompat"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49b0e56393adf13677796fe919fede8de0db707c0e2f67b2fa3013434db49575"
+dependencies = [
+ "async-native-tls",
+ "async-trait",
+ "async_executors",
+ "educe",
+ "futures",
+ "native-tls",
+ "pin-project",
+ "thiserror",
+ "tokio",
+ "tokio-util",
+]
+
+[[package]]
+name = "tor-rtmock"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79c9c6cf6060047a44803fd65f0b2ff79ae353d507ed324c51da984dd6d01537"
+dependencies = [
+ "async-trait",
+ "futures",
+ "pin-project",
+ "thiserror",
+ "tor-rtcompat",
+ "tracing",
+]
+
+[[package]]
+name = "tor-units"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "242194792bccb9960b9d141b6213dcb9ac0548238a4afeb55eed7b69ceb13a5d"
+dependencies = [
+ "derive_more",
+ "thiserror",
+]
+
 [[package]]
 name = "tower-service"
 version = "0.3.2"
@@ -2624,9 +4495,21 @@ checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
 dependencies = [
  "cfg-if",
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
 ]
 
+[[package]]
+name = "tracing-attributes"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "tracing-core"
 version = "0.1.29"
@@ -2690,6 +4573,24 @@ version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
 
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "untrusted"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
+
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
 [[package]]
 name = "url"
 version = "2.3.1"
@@ -2701,6 +4602,16 @@ dependencies = [
  "percent-encoding",
 ]
 
+[[package]]
+name = "users"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
+dependencies = [
+ "libc",
+ "log",
+]
+
 [[package]]
 name = "vcpkg"
 version = "0.2.15"
@@ -2719,6 +4630,12 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+
 [[package]]
 name = "walkdir"
 version = "2.3.2"
@@ -2907,6 +4824,12 @@ dependencies = [
  "pkg-config",
 ]
 
+[[package]]
+name = "weak-table"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549"
+
 [[package]]
 name = "web-sys"
 version = "0.3.60"
@@ -2931,6 +4854,16 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted 0.7.1",
+]
+
 [[package]]
 name = "weezl"
 version = "0.1.7"
@@ -2989,43 +4922,100 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
 dependencies = [
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_msvc",
+ "windows_aarch64_msvc 0.36.1",
+ "windows_i686_gnu 0.36.1",
+ "windows_i686_msvc 0.36.1",
+ "windows_x86_64_gnu 0.36.1",
+ "windows_x86_64_msvc 0.36.1",
 ]
 
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+
 [[package]]
 name = "winit"
 version = "0.27.3"
@@ -3055,7 +5045,7 @@ dependencies = [
  "wayland-client",
  "wayland-protocols",
  "web-sys",
- "windows-sys",
+ "windows-sys 0.36.1",
  "x11-dl",
 ]
 
@@ -3100,6 +5090,26 @@ dependencies = [
  "winapi-wsapoll",
 ]
 
+[[package]]
+name = "x25519-dalek"
+version = "2.0.0-pre.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df"
+dependencies = [
+ "curve25519-dalek",
+ "rand_core 0.6.4",
+ "zeroize",
+]
+
+[[package]]
+name = "xattr"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "xcursor"
 version = "0.3.4"
@@ -3116,7 +5126,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
 
 [[package]]
-name = "zeroize"
-version = "1.3.0"
+name = "xz2"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
+checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
+dependencies = [
+ "lzma-sys",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zstd"
+version = "0.11.2+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
+dependencies = [
+ "zstd-safe",
+]
+
+[[package]]
+name = "zstd-safe"
+version = "5.0.2+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
+dependencies = [
+ "libc",
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-sys"
+version = "2.0.1+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b"
+dependencies = [
+ "cc",
+ "libc",
+]
diff --git a/Cargo.toml b/Cargo.toml
index a705ac6..31b979e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,27 +4,41 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-dirs = "4.0.0"
+anyhow = "1.0.65"
+arti-client = "0.7.0"
+arti-hyper = "0.7.0"
+bytes = "1.2.1"
 chrono = "0.4.22"
+dirs = "4.0.0"
 eframe = "0.19.0"
 egui = "0.19.0"
 egui_extras = { version = "0.19.0", features = ["image"] }
 env_logger = "0.9.1"
 figment = { version = "0.10.8", features = ["toml"] }
+flate2 = "1.0"
 hex-literal = "0.3.4"
+hyper = "0.14.20"
+hyper-tls = "0.5.0"
 image = { version = "0.24.4", features = ["png"] }
 log = "0.4.17"
 monero = "0.18.0"
 num_cpus = "1.13.1"
 num-format = "0.4.0"
+openssl = { version = "*", features = ["vendored"] }
 rand = "0.8.5"
 regex = "1.6.0"
 reqwest = { version = "0.11.12", features = ["blocking", "json"] }
 serde = "1.0.145"
 serde_derive = "1.0.145"
+serde_json = "1.0"
 sha2 = "0.10.6"
+tar = "0.4.38"
+tls-api = "0.9.0"
+tls-api-native-tls = "0.9.0"
+tokio = { version = "1.21.2", features = ["full"] }
 toml = "0.5.9"
-openssl = { version = "*", features = ["vendored"] }
+tor-rtcompat = "0.7.0"
+walkdir = "2.3.2"
 
 [profile.optimized]
 codegen-units = 1
diff --git a/src/constants.rs b/src/constants.rs
index b527597..2efa9d4 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -26,11 +26,6 @@ pub const P2POOL_BASE_ARGS: &'static str = "";
 pub const XMRIG_BASE_ARGS: &'static str = "--http-host=127.0.0.1 --http-port=18088 --algo=rx/0 --coin=Monero --randomx-cache-qos";
 pub const HORIZONTAL: &'static str = "--------------------------------------------";
 
-// Update data
-pub const GITHUB_METADATA_GUPAX: &'static str = "https://api.github.com/repos/hinto-janaiyo/gupax/releases/latest";
-pub const GITHUB_METADATA_P2POOL: &'static str = "https://api.github.com/repos/SChernykh/p2pool/releases/latest";
-pub const GITHUB_METADATA_XMRIG: &'static str = "https://api.github.com/repos/xmrig/xmrig/releases/latest";
-
 // OS specific
 #[cfg(target_os = "windows")]
 pub const OS: &'static str = " Windows";
diff --git a/src/gupax.rs b/src/gupax.rs
index 581f0e5..6ed374f 100644
--- a/src/gupax.rs
+++ b/src/gupax.rs
@@ -20,6 +20,7 @@ use crate::App;
 use egui::WidgetType::Button;
 use crate::constants::*;
 use crate::state::Gupax;
+use crate::update::*;
 
 impl Gupax {
 	pub fn show(state: &mut Gupax, ctx: &egui::Context, ui: &mut egui::Ui) {
diff --git a/src/main.rs b/src/main.rs
index 0acddad..bbd7237 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -50,7 +50,8 @@ mod status;
 mod gupax;
 mod p2pool;
 mod xmrig;
-use {ferris::*,constants::*,node::*,state::*,about::*,status::*,gupax::*,p2pool::*,xmrig::*};
+mod update;
+use {ferris::*,constants::*,node::*,state::*,about::*,status::*,gupax::*,p2pool::*,xmrig::*,update::*};
 
 //---------------------------------------------------------------------------------------------------- Struct + Impl
 // The state of the outer main [App].
@@ -66,15 +67,11 @@ pub struct App {
 	node: Arc<Mutex<NodeStruct>>, // Data on community nodes
 	width: f32, // Top-level width
 	height: f32, // Top-level height
-	// State:
-	// og    = Old state to compare against
-	// state = Working state (current settings)
-	// Instead of comparing [og == state] every frame,
-	// the [diff] bool will be the signal for [Reset/Save].
-	og: State,
-	state: State,
-//	update: Update, // State for update data [update.rs]
-	diff: bool,
+	// State
+	og: State, // og    = Old state to compare against
+	state: State, // state = Working state (current settings)
+	update: Update, // State for update data [update.rs]
+	diff: bool, // Instead of comparing [og == state] every frame, this bool indicates changes
 	// Process/update state:
 	// Doesn't make sense to save this on disk
 	// so it's represented as a bool here.
@@ -105,6 +102,7 @@ impl App {
 	}
 
 	fn new() -> Self {
+		let throwaway = State::default();
 		let app = Self {
 			tab: Tab::default(),
 			quit: false,
@@ -116,7 +114,7 @@ impl App {
 			node: Arc::new(Mutex::new(NodeStruct::default())),
 			og: State::default(),
 			state: State::default(),
-//			update: Update::default(),
+			update: Update::new(&throwaway.gupax.absolute_p2pool_path, &throwaway.gupax.absolute_xmrig_path, true),
 			diff: false,
 			p2pool: false,
 			xmrig: false,
@@ -133,7 +131,7 @@ impl App {
 		};
 		// Apply arg state
 		let mut app = parse_args(app);
-		// Get exe path + random tmp folder 
+		// Get exe path + random tmp folder
 		app.exe = match get_exe_dir() {
 			Ok(exe) => exe,
 			Err(err) => { panic_app(err.to_string()); exit(1); },
@@ -149,6 +147,7 @@ impl App {
 		app.og.xmrig.max_threads = num_cpus::get();
 		if app.og.xmrig.current_threads > app.og.xmrig.max_threads { app.og.xmrig.current_threads = app.og.xmrig.max_threads; }
 		app.state = app.og.clone();
+		app.update = Update::new(&app.og.gupax.absolute_p2pool_path, &app.og.gupax.absolute_xmrig_path, app.og.gupax.update_via_tor);
 		app
 	}
 }
@@ -273,14 +272,23 @@ fn parse_args(mut app: App) -> App {
 	app
 }
 
-fn get_exe_dir() -> Result<String, std::io::Error> {
+// Get absolute [Gupax] binary path
+pub fn get_exe() -> Result<String, std::io::Error> {
 	match std::env::current_exe() {
-		Ok(mut path) => { path.pop(); Ok(path.into_os_string().into_string().unwrap()) },
+		Ok(mut path) => { Ok(path.display().to_string()) },
 		Err(err) => { error!("Couldn't get exe basepath PATH"); return Err(err) },
 	}
 }
 
-fn get_rand_tmp(path: &String) -> String {
+// Get absolute [Gupax] directory path
+pub fn get_exe_dir() -> Result<String, std::io::Error> {
+	match std::env::current_exe() {
+		Ok(mut path) => { path.pop(); Ok(path.display().to_string()) },
+		Err(err) => { error!("Couldn't get exe basepath PATH"); return Err(err) },
+	}
+}
+
+pub fn get_rand_tmp(path: &String) -> String {
 	use rand::{thread_rng, Rng};
 	use rand::distributions::Alphanumeric;
     let rand: String = thread_rng()
@@ -361,6 +369,11 @@ impl eframe::App for App {
 	}
 
 	fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
+		// *-------*
+		// | DEBUG |
+		// *-------*
+		self.update.start();
+		thread::sleep;
 		// This sets the top level Ui dimensions.
 		// Used as a reference for other uis.
 		egui::CentralPanel::default().show(ctx, |ui| { self.width = ui.available_width(); self.height = ui.available_height(); });
diff --git a/src/node.rs b/src/node.rs
index ff9eb7a..007cbe9 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -103,7 +103,7 @@ impl NodeStruct {
 	// find the fastest/slowest one for the user.
 	// The process:
 	//   - Send [get_info] JSON-RPC requests over HTTP
-	//   - To prevent fingerprinting, randomly send [1-5] calls
+	//   - To prevent fingerprinting, randomly send [2-4] calls
 	//   - Measure each request in milliseconds as [u128]
 	//   - Timeout on requests over 5 seconds
 	//   - Calculate average time
@@ -121,16 +121,26 @@ impl NodeStruct {
 	// default = GRAY
 	pub fn ping() -> PingResult {
 		info!("Starting community node pings...");
+		// Get node list
 		let mut nodes = NodeStruct::default();
+
+		// Create JSON request
 		let mut get_info = HashMap::new();
 		get_info.insert("jsonrpc", "2.0");
 		get_info.insert("id", "0");
 		get_info.insert("method", "get_info");
+
+		// Misc Settings
 		let mut vec: Vec<(u128, NodeEnum)> = Vec::new();
-		let fastest = false;
+
+		// Create HTTP Client
 		let timeout_sec = Duration::from_millis(5000);
+		let client = reqwest::blocking::ClientBuilder::new();
+		let client = reqwest::blocking::ClientBuilder::timeout(client, timeout_sec);
+		let client = reqwest::blocking::ClientBuilder::build(client).unwrap();
 
 		for ip in NODE_IPS.iter() {
+			// Match IP
 			let id = match *ip {
 				C3POOL        => C3pool,
 				CAKE          => Cake,
@@ -143,27 +153,28 @@ impl NodeStruct {
 				SETH          => Seth,
 				SUPPORTXMR    => SupportXmr,
 				SUPPORTXMR_IR => SupportXmrIr,
-//				XMRVSBEAST    => XmrVsBeast,
 				_ => XmrVsBeast,
 			};
+			// Misc
 			let mut timeout = false;
 			let mut mid = Duration::new(0, 0);
-			let max = rand::thread_rng().gen_range(1..5);
+			let max = rand::thread_rng().gen_range(2..4);
+
+			// Start JSON-RPC request
 			for i in 1..=max {
-				let client = reqwest::blocking::ClientBuilder::new();
-				let client = reqwest::blocking::ClientBuilder::timeout(client, timeout_sec);
-				let client = reqwest::blocking::ClientBuilder::build(client).unwrap();
-				let http = "http://".to_owned() + &**ip + "/json_rpc";
 				let now = Instant::now();
+				let http = "http://".to_owned() + &**ip + "/json_rpc";
 				match client.post(http).json(&get_info).send() {
-					Ok(r) => mid += now.elapsed(),
+					Ok(_) => mid += now.elapsed(),
 					Err(err) => {
-						error!("Timeout on [{:#?}: {}] (over 5 seconds)", id, ip);
+						error!("Timeout on [{:#?}: {}] (over 5 seconds) | {}", id, ip, err);
 						mid += timeout_sec;
 						timeout = true;
 					},
 				};
 			}
+
+			// Calculate average
 			let ms = mid.as_millis() / 3;
 			vec.push((ms, id));
 			info!("{}ms ... {} calls ... {}", ms, max, ip);
@@ -192,6 +203,8 @@ impl NodeStruct {
 				XmrVsBeast   => { nodes.xmrvsbeast.ms = ms; nodes.xmrvsbeast.color = color; },
 			}
 		}
+
+		// Calculate fastest out of all nodes
 		let mut best_ms: u128 = vec[0].0;
 		let mut fastest: NodeEnum = vec[0].1;
 		for (ms, id) in vec.iter() {
diff --git a/src/state.rs b/src/state.rs
index bf1bda4..677f2f7 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -51,6 +51,7 @@ impl State {
 				auto_node: true,
 				ask_before_quit: true,
 				save_before_quit: true,
+				update_via_tor: true,
 				p2pool_path: DEFAULT_P2POOL_PATH.to_string(),
 				xmrig_path: DEFAULT_XMRIG_PATH.to_string(),
 				absolute_p2pool_path: Self::into_absolute_path(DEFAULT_P2POOL_PATH.to_string()).unwrap(),
@@ -300,6 +301,7 @@ pub struct Gupax {
 	pub auto_node: bool,
 	pub ask_before_quit: bool,
 	pub save_before_quit: bool,
+	pub update_via_tor: bool,
 	pub p2pool_path: String,
 	pub xmrig_path: String,
 	pub absolute_p2pool_path: PathBuf,
diff --git a/src/update.rs b/src/update.rs
index a140a9a..77a44bc 100644
--- a/src/update.rs
+++ b/src/update.rs
@@ -14,54 +14,455 @@
 //// You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-use crate::State;
+//---------------------------------------------------------------------------------------------------- Imports
+use serde_derive::{Serialize,Deserialize};
+use tokio::task::JoinHandle;
+use std::time::Duration;
+use std::sync::{Arc,Mutex};
+use std::os::unix::fs::OpenOptionsExt;
+use std::io::{Read,Write};
+//use crate::{Name::*,State};
+use rand::{thread_rng, Rng};
+use rand::distributions::Alphanumeric;
+use anyhow::Error;
+use arti_hyper::*;
+use arti_client::{TorClient,TorClientConfig};
+use tokio::io::{AsyncReadExt,AsyncWriteExt};
+use tls_api::{TlsConnector, TlsConnectorBuilder};
+use hyper::header::HeaderValue;
+use hyper::{Client,Body,Request};
+use hyper_tls::HttpsConnector;
+use arti_hyper::*;
+use log::*;
+use crate::update::Name::*;
+use std::path::PathBuf;
 
-struct Update {
-	new_gupax: String,
-	new_p2pool: String,
-	new_xmrig: String,
-	path_gupax: String,
-	path_p2pool: String,
-	path_xmrig: String,
-	updating: Arc<Mutex<bool>> // Is the update in progress?
-	update_prog: u8, // Not an [f32] because [Eq] doesn't work
+// use tls_api_native_tls::{TlsConnector,TlsConnectorBuilder};
+
+//---------------------------------------------------------------------------------------------------- Constants
+// Package naming schemes:
+// gupax  | gupax-vX.X.X-(windows|macos|linux)-x64.(zip|tar.gz)
+// p2pool | p2pool-vX.X.X-(windows|macos|linux)-x64.(zip|tar.gz)
+// xmrig  | xmrig-X.X.X-(msvc-win64|macos-x64|linux-static-x64).(zip|tar.gz)
+//
+// Download link = PREFIX + Version (found at runtime) + SUFFIX + Version + EXT
+// Example: https://github.com/hinto-janaiyo/gupax/releases/download/v0.0.1/gupax-v0.0.1-linux-standalone-x64
+//
+// Exceptions (there are always exceptions...):
+//   - XMRig doesn't have a [v], so it is [xmrig-6.18.0-...]
+//   - XMRig separates the hash and signature
+//   - P2Pool hashes are in UPPERCASE
+//   - Gupax will be downloaded as a standalone binary (no decompression/extraction needed)
+
+const GUPAX_METADATA: &'static str = "https://api.github.com/repos/hinto-janaiyo/gupax/releases/latest";
+const P2POOL_METADATA: &'static str = "https://api.github.com/repos/SChernykh/p2pool/releases/latest";
+const XMRIG_METADATA: &'static str = "https://api.github.com/repos/xmrig/xmrig/releases/latest";
+
+const GUPAX_PREFIX: &'static str = "https://github.com/hinto-janaiyo/gupax/releases/download/";
+const P2POOL_PREFIX: &'static str = "https://github.com/SChernykh/p2pool/releases/download/";
+const XMRIG_PREFIX: &'static str = "https://github.com/xmrig/xmrig/releases/download/";
+
+const GUPAX_SUFFIX: &'static str = "/gupax-";
+const P2POOL_SUFFIX: &'static str = "/p2pool-";
+const XMRIG_SUFFIX: &'static str = "/xmrig-";
+
+const GUPAX_HASH: &'static str = "SHA256SUMS";
+const P2POOL_HASH: &'static str = "sha256sums.txt.asc";
+const XMRIG_HASH: &'static str = "SHA256SUMS";
+
+#[cfg(target_os = "windows")]
+const GUPAX_EXTENSION: &'static str = "-windows-standalone-x64.exe";
+#[cfg(target_os = "windows")]
+const P2POOL_EXTENSION: &'static str = "-windows-x64.zip";
+#[cfg(target_os = "windows")]
+const XMRIG_EXTENSION: &'static str = "-msvc-win64.zip";
+
+#[cfg(target_os = "macos")]
+const GUPAX_EXTENSION: &'static str = "-macos-standalone-x64";
+#[cfg(target_os = "macos")]
+const P2POOL_EXTENSION: &'static str = "-macos-x64.tar.gz";
+#[cfg(target_os = "macos")]
+const XMRIG_EXTENSION: &'static str = "-macos-x64.tar.gz";
+
+#[cfg(target_os = "linux")]
+const GUPAX_EXTENSION: &'static str = "-linux-standalone-x64";
+#[cfg(target_os = "linux")]
+const P2POOL_EXTENSION: &'static str = "-linux-x64.tar.gz";
+#[cfg(target_os = "linux")]
+const XMRIG_EXTENSION: &'static str = "-linux-static-x64.tar.gz";
+
+// Some fake Curl/Wget user-agents because GitHub API requires one and a Tor browser
+// user-agent might be fingerprintable without all the associated headers.
+const FAKE_USER_AGENT: [&'static str; 50] = [
+	"Wget/1.16.3",
+	"Wget/1.17",
+	"Wget/1.17.1",
+	"Wget/1.18",
+	"Wget/1.18",
+	"Wget/1.19",
+	"Wget/1.19.1",
+	"Wget/1.19.2",
+	"Wget/1.19.3",
+	"Wget/1.19.4",
+	"Wget/1.19.5",
+	"Wget/1.20",
+	"Wget/1.20.1",
+	"Wget/1.20.2",
+	"Wget/1.20.3",
+	"Wget/1.21",
+	"Wget/1.21.1",
+	"Wget/1.21.2",
+	"Wget/1.21.3",
+	"curl/7.64.1",
+	"curl/7.65.0",
+	"curl/7.65.1",
+	"curl/7.65.2",
+	"curl/7.65.3",
+	"curl/7.66.0",
+	"curl/7.67.0",
+	"curl/7.68.0",
+	"curl/7.69.0",
+	"curl/7.69.1",
+	"curl/7.70.0",
+	"curl/7.70.1",
+	"curl/7.71.0",
+	"curl/7.71.1",
+	"curl/7.72.0",
+	"curl/7.73.0",
+	"curl/7.74.0",
+	"curl/7.75.0",
+	"curl/7.76.0",
+	"curl/7.76.1",
+	"curl/7.77.0",
+	"curl/7.78.0",
+	"curl/7.79.0",
+	"curl/7.79.1",
+	"curl/7.80.0",
+	"curl/7.81.0",
+	"curl/7.82.0",
+	"curl/7.83.0",
+	"curl/7.83.1",
+	"curl/7.84.0",
+	"curl/7.85.0",
+];
+
+const MSG_START: &'static str = "Starting update...";
+const MSG_TMP: &'static str = "Creating temporary directory";
+const MSG_PKG: &'static str = "Creating package list";
+const MSG_TOR: &'static str = "Creating Tor+HTTPS client";
+const MSG_HTTPS: &'static str = "Creating HTTPS client";
+const MSG_METADATA: &'static str = "Fetching package metadata";
+const MSG_ARCHIVE: &'static str = "Downloading packages";
+
+// These two are sequential and not async so no need for a constant message.
+// The package in question will be known at runtime, so that will be printed.
+//const MSG_EXTRACT: &'static str = "Extracting packages";
+//const MSG_UPGRADE: &'static str = "Upgrading packages";
+
+//---------------------------------------------------------------------------------------------------- Update struct/impl
+// Contains values needed during update
+// Progress bar structure:
+// 5%  | Create tmp directory
+// 5%  | Create package list
+// 10% | Create Tor/HTTPS client
+// 20% | Download Metadata (x3)
+// 30% | Download Archive (x3)
+// 15% | Extract (x3)
+// 15% | Upgrade (x3)
+
+pub struct Update {
+	path_gupax: String, // Full path to current gupax
+	path_p2pool: String, // Full path to current p2pool
+	path_xmrig: String, // Full path to current xmrig
+	tmp_dir: String, // Full path to temporary directory
+	updating: Arc<Mutex<bool>>, // Is an update in progress?
+	prog: Arc<Mutex<u8>>, // Holds the 0-100% progress bar number
+	msg: Arc<Mutex<String>>, // Message to display on [Gupax] tab while updating
+	tor: bool, // Is Tor enabled or not?
 }
 
 impl Update {
-	fn new(path_p2pool: String, path_xmrig: String) -> Result<Self, Error> {
-		let path_gupax = std::env::current_exe()?;
+	// Takes in current paths from [State]
+	pub fn new(path_p2pool: &PathBuf, path_xmrig: &PathBuf, tor: bool) -> Self {
 		Self {
-			new_gupax: "?".to_string(),
-			new_p2pool: "?".to_string(),
-			new_xmrig: "?".to_string(),
-			path_gupax,
-			path_p2pool,
-			path_xmrig,
-			updating: Arc::new(Mutex::new(false)),
-			update_prog: 0,
+			path_gupax: crate::get_exe().unwrap(),
+			path_p2pool: path_p2pool.display().to_string(),
+			path_xmrig: path_xmrig.display().to_string(),
+			tmp_dir: "".to_string(),
+			updating: Arc::new(Mutex::new(true)),
+			prog: Arc::new(Mutex::new(0)),
+			msg: Arc::new(Mutex::new("".to_string())),
+			tor,
 		}
 	}
 
-	fn update(state: &mut State) -> Result((), Error) {
-
+	// Get a temporary random folder
+	// for package download contents
+	// Will look like [/tmp/gupax_A1m98FN3fa/] on Unix
+	pub fn get_tmp_dir() -> String {
+		let rand_string: String = thread_rng()
+			.sample_iter(&Alphanumeric)
+			.take(10)
+			.map(char::from)
+			.collect();
+		let tmp = std::env::temp_dir();
+		let tmp = format!("{}{}{}{}", tmp.display(), "/gupax_", rand_string, "/");
+		info!("Update | TMP directory ... {}", tmp);
+		tmp
 	}
 
+	// The HTTPS client created when Tor is enabled:
+	//     TLS implementation | tls-api -> native-tls
+	//     Tor implementatoin | arti
+	pub async fn get_tor_client() -> Result<ClientEnum, anyhow::Error> {
+		info!("Update | Creating Tor+HTTPS client...");
+		let tor = TorClient::create_bootstrapped(TorClientConfig::default()).await?;
+		let tls = tls_api_native_tls::TlsConnector::builder()?.build()?;
+	    let http = ArtiHttpConnector::new(tor, tls);
+		let client = ClientEnum::Tor(Client::builder().build(http));
+		info!("Update | Tor client ... OK");
+		Ok(client)
+	}
+
+	// The HTTPS client created when Tor is disabled:
+	//     TLS implementation | hyper-tls
+	pub async fn get_client() -> Result<ClientEnum, anyhow::Error> {
+		info!("Update | Creating HTTPS client...");
+		let mut https = hyper_tls::HttpsConnector::new();
+		https.https_only(true);
+		let client = ClientEnum::Https(Client::builder().build(https));
+		info!("Update | HTTPS client ... OK");
+		Ok(client)
+	}
+
+	// Download process:
+	// 0. setup tor, client, http, etc
+	// 1. fill vector with all enums
+	// 2. loop over vec, download metadata
+	// 3. if current == version, remove from vec
+	// 4. loop over vec, download links
+	// 5. extract, upgrade
+
+	#[tokio::main]
+	pub async fn start(&mut self) -> Result<(), anyhow::Error> {
+		// Set progress bar
+		*self.msg.lock().unwrap() = MSG_START.to_string();
+		*self.prog.lock().unwrap() = 0;
+
+		// Get temporary directory
+		*self.msg.lock().unwrap() = MSG_TMP.to_string();
+		let tmp_dir = Self::get_tmp_dir();
+		*self.prog.lock().unwrap() = 5;
+
+		// Make Pkg vector
+		*self.msg.lock().unwrap() = MSG_PKG.to_string();
+		let vec = vec![
+			Pkg::new(Gupax, &tmp_dir, self.prog.clone(), self.msg.clone()),
+			Pkg::new(P2pool, &tmp_dir, self.prog.clone(), self.msg.clone()),
+			Pkg::new(Xmrig, &tmp_dir, self.prog.clone(), self.msg.clone()),
+		];
+		let mut handles: Vec<JoinHandle<()>> = vec![];
+		*self.prog.lock().unwrap() = 5;
+
+		// Create Tor/HTTPS client
+		let mut client: ClientEnum;
+		if self.tor {
+			*self.msg.lock().unwrap() = MSG_TOR.to_string();
+			client = Self::get_tor_client().await?;
+		} else {
+			*self.msg.lock().unwrap() = MSG_HTTPS.to_string();
+			client = Self::get_client().await?;
+		}
+		*self.prog.lock().unwrap() = 10;
+
+		// loop for metadata
+		for pkg in vec.iter() {
+			info!("Update | Metadata | Starting ... {}", pkg.name);
+			let name = pkg.name.clone();
+			let version = Arc::clone(&pkg.version);
+			let request = hyper::Request::builder()
+				.method("GET")
+				.uri(pkg.link_metadata)
+				.header(hyper::header::USER_AGENT, hyper::header::HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"))
+				.body(Body::empty())?;
+			let client = client.clone();
+			let handle: JoinHandle<()> = tokio::spawn(async move {
+				Pkg::get_tor_response(name, version, client, request).await;
+			});
+			handles.push(handle);
+		}
+		for handle in handles {
+			handle.await?;
+		}
+		info!("Update | Metadata ... OK\n");
+		Ok(())
+
+	//----------------------------------------------
+	//
+	//	// loop for download
+	//	let mut handles: Vec<JoinHandle<()>> = vec![];
+	//	for pkg in vec.iter() {
+	//		let name = pkg.name.clone();
+	//		let bytes = Arc::clone(&pkg.bytes);
+	//		let version = pkg.version.lock().unwrap();
+	//		let link;
+	//		if pkg.name == Name::Xmrig {
+	//			link = pkg.link_prefix.clone() + &version + &pkg.link_suffix_1 + &version[1..] + &pkg.link_suffix_2;
+	//		} else {
+	//			link = pkg.link_prefix.clone() + &version + &pkg.link_suffix_1 + &version + &pkg.link_suffix_2;
+	//		}
+	//		println!("download: {:#?} | {}", pkg.name, link);
+	//		let request = Client::get(&client.clone(), &link);
+	//		let handle: JoinHandle<()> = tokio::spawn(async move {
+	//			get_bytes(request, bytes, name).await;
+	//		});
+	//		handles.push(handle);
+	//	}
+	//	for handle in handles {
+	//		handle.await.unwrap();
+	//	}
+	//	println!("download ... OK\n");
+	//
+	//	// extract
+	//	let TMP = num();
+	//	std::fs::create_dir(&TMP).unwrap();
+	//	for pkg in vec.iter() {
+	//		let name = TMP.to_string() + &pkg.name.to_string();
+	//		println!("extract: {:#?} | {}", pkg.name, name);
+	//		if pkg.name == Name::Gupax {
+	//			std::fs::OpenOptions::new().mode(0o700).create(true).write(true).open(&name);
+	//			std::fs::write(name, pkg.bytes.lock().unwrap().as_ref()).unwrap();
+	//		} else {
+	//			std::fs::create_dir(&name).unwrap();
+	//			tar::Archive::new(flate2::read::GzDecoder::new(pkg.bytes.lock().unwrap().as_ref())).unpack(name).unwrap();
+	//		}
+	//	}
+	//	println!("extract ... OK");
+	//
+	//async fn get_bytes(request: RequestBuilder, bytes: Arc<Mutex<bytes::Bytes>>, name: Name) {
+	//	*bytes.lock().unwrap() = request.send().await.unwrap().bytes().await.unwrap();
+	//	println!("{} download ... OK", name);
+	//}
+	//
+	//async fn func(request: RequestBuilder, version: Arc<Mutex<String>>, name: Name) {
+	//	let response = request.send().await.unwrap().bytes().await.unwrap();
+	//
+	//	let mut bytes = flate2::read::GzDecoder::new(response.as_ref());
+	//	let mut response = String::new();
+	//	bytes.read_to_string(&mut response).unwrap();
+	//
+	//	let response: Version = serde_json::from_str(&response).unwrap();
+	//	*version.lock().unwrap() = response.tag_name.clone();
+	//	println!("{} {} ... OK", name, response.tag_name);
+	//}
+	}
+}
+
+// Wrapper type around Tor/HTTPS client
+enum ClientEnum {
+	Tor(Client<ArtiHttpConnector<tor_rtcompat::PreferredRuntime, tls_api_native_tls::TlsConnector>>),
+	Https(Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>),
+}
+
+//---------------------------------------------------------------------------------------------------- Pkg struct/impl
+#[derive(Debug)]
+pub struct Pkg {
+	name: Name,
+	link_metadata: &'static str,
+	link_prefix: &'static str,
+	link_suffix: &'static str,
+	link_extension: &'static str,
+	tmp_dir: String,
+	update_prog: Arc<Mutex<u8>>,
+	update_msg: Arc<Mutex<String>>,
+	bytes: Arc<Mutex<bytes::Bytes>>,
+	version: Arc<Mutex<String>>,
+}
+
+impl Pkg {
+	pub fn new(name: Name, tmp_dir: &String, update_prog: Arc<Mutex<u8>>, update_msg: Arc<Mutex<String>>) -> Self {
+		let link_metadata = match name {
+			Gupax => GUPAX_METADATA,
+			P2pool => P2POOL_METADATA,
+			Xmrig => XMRIG_METADATA,
+		};
+		let link_prefix = match name {
+			Gupax => GUPAX_PREFIX,
+			P2pool => P2POOL_PREFIX,
+			Xmrig => XMRIG_PREFIX,
+		};
+		let link_suffix = match name {
+			Gupax => GUPAX_SUFFIX,
+			P2pool => P2POOL_SUFFIX,
+			Xmrig => XMRIG_SUFFIX,
+		};
+		let link_extension = match name {
+			Gupax => GUPAX_EXTENSION,
+			P2pool => P2POOL_EXTENSION,
+			Xmrig => XMRIG_EXTENSION,
+		};
+		Self {
+			name,
+			link_metadata,
+			link_prefix,
+			link_suffix,
+			link_extension,
+			tmp_dir: tmp_dir.to_string(),
+			update_prog,
+			update_msg,
+			bytes: Arc::new(Mutex::new(bytes::Bytes::new())),
+			version: Arc::new(Mutex::new(String::new())),
+		}
+	}
+
+	// Generate GET request based off input URI + fake user agent
+	pub async fn get_request(self) -> Result<Request<Body>, anyhow::Error> {
+		let user_agent = FAKE_USER_AGENT[thread_rng().gen_range(0..50)];
+		let request = Request::builder()
+			.method("GET")
+			.uri(self.link_metadata)
+			.header(hyper::header::USER_AGENT, HeaderValue::from_static(user_agent))
+			.body(Body::empty())?;
+		Ok(request)
+	}
+
+	// Get response using [Tor client] + [request]
+	// and change the [version] under an Arc<Mutex>
+	pub async fn get_tor_response(name: Name, version: Arc<Mutex<String>>, client: Client<ArtiHttpConnector<tor_rtcompat::PreferredRuntime, tls_api_native_tls::TlsConnector>>, request: Request<Body>) -> Result<(), Error> {
+		let mut response = client.request(request).await?;
+		let body = hyper::body::to_bytes(response.body_mut()).await?;
+		let body: Version = serde_json::from_slice(&body)?;
+		*version.lock().unwrap() = body.tag_name.clone();
+		info!("Update | Metadata | {} {} ... OK", name, body.tag_name);
+		Ok(())
+	}
+
+	// Same thing, but without Tor.
+	pub async fn get_response(name: Name, version: Arc<Mutex<String>>, client: Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>, request: Request<Body>) -> Result<(), Error> {
+		let mut response = client.request(request).await?;
+		let body = hyper::body::to_bytes(response.body_mut()).await?;
+		let body: Version = serde_json::from_slice(&body)?;
+		*version.lock().unwrap() = body.tag_name.clone();
+		info!("Update | Metadata | {} {} ... OK", name, body.tag_name);
+		Ok(())
+	}
+}
+
+// This inherits the value of [tag_name] from GitHub's JSON API
 #[derive(Debug, Serialize, Deserialize)]
-struct TagName {
+struct Version {
 	tag_name: String,
 }
 
-#[derive(Debug, Serialize, Deserialize)]
-enum Error {
-	Io(std::io::Error),
-	Serialize(toml::ser::Error),
-	Deserialize(toml::de::Error),
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-enum Package {
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
+pub enum Name {
 	Gupax,
 	P2pool,
 	Xmrig,
 }
 
+impl std::fmt::Display for Name {
+	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+		write!(f, "{:?}", self)
+	}
+}