Compare commits
484 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f4492b4b13 | |||
| 5585a83e3e | |||
| 308af24881 | |||
| 50d7fc73cb | |||
| 01043d7940 | |||
| 2d1961b8be | |||
| e891c68158 | |||
| b1fb032f43 | |||
| 23ea82952e | |||
| 9a65e44166 | |||
| 020cad897d | |||
| 5dfaff6296 | |||
| 5b03982043 | |||
| 8f6856d6fb | |||
| 976dd7aae2 | |||
| 0d21f4e937 | |||
| 1403449ad5 | |||
| e84af4f601 | |||
| 26b032c15c | |||
| cba3625394 | |||
| e1ddaff04d | |||
| 66ab5de442 | |||
| 0b9c03ca90 | |||
| c9dce0c1da | |||
| e00e77db15 | |||
| 1074449f91 | |||
| 08276e6e42 | |||
| 9a3d824a4a | |||
| 2789ee8f18 | |||
| a7ba643c35 | |||
| 28be53eefb | |||
| 219c45a352 | |||
| 1a3b83752e | |||
| c42f3c6844 | |||
| a5d3ba3900 | |||
| cdf0d44341 | |||
| 92f976a45d | |||
| 2bc858cde3 | |||
| 92e13a5d00 | |||
| 122f5d9f2e | |||
| 982ee0266c | |||
| 5f42a9bd05 | |||
| 1811df9ddb | |||
| 6bdfe7f895 | |||
| c6b286a1db | |||
| b3568a26f5 | |||
| 15ae0f521e | |||
| 2923d4b872 | |||
| d740e8b8a9 | |||
| a274edffba | |||
| eec211e038 | |||
| f5f888a0aa | |||
| 86ec1d6026 | |||
| bc3f5838f1 | |||
| 7e58b3273d | |||
| bed09bf8a4 | |||
| 28e55c6de6 | |||
| abb4537551 | |||
| b48f2f1660 | |||
| ccf8063a52 | |||
| 8694396942 | |||
| fb253e53a4 | |||
| fdd34863ba | |||
| 4ac95ad8cf | |||
| 132d550cb6 | |||
| efc5035144 | |||
| ebeac73f30 | |||
| 5303288b9c | |||
| bcac045c77 | |||
| d643df74b3 | |||
| 4c1c6d86c8 | |||
| 623448a220 | |||
| b403ce1e62 | |||
| 6faf8786ea | |||
| aaa4378b33 | |||
| 6512bfb4d9 | |||
| 1afabfd1b6 | |||
| f05e2880a9 | |||
| 81675008a6 | |||
| 8b4fc5719e | |||
| e4f7452241 | |||
| 9602379368 | |||
| 35ba39c196 | |||
| 6d09da40e0 | |||
| de44f21d64 | |||
| edc91e0e36 | |||
| 518cd21fd6 | |||
| b36ca2c4f1 | |||
| 2db79de722 | |||
| 3a9531b586 | |||
| f96d768341 | |||
| 26fb13fe2d | |||
| 67a9d80299 | |||
| 84249cab4b | |||
| f4305dfaa5 | |||
| 0c45c61c85 | |||
| 7d250b3384 | |||
| bb2029e21c | |||
| 0f0611f390 | |||
| 2904141c14 | |||
| c569a7a858 | |||
| 87db1fd8c1 | |||
| a1d2d09f28 | |||
| b949d7b221 | |||
| de468760d6 | |||
| 30a78df986 | |||
| e8622a190a | |||
| 75f098f002 | |||
| b034a07439 | |||
| 68956456dd | |||
| aa048cabe6 | |||
| 5dc67b995e | |||
| 721e4bda8b | |||
| 2673f83116 | |||
| bc68513a78 | |||
| 91250f199a | |||
| 3ec92a0784 | |||
| 70a9317ab3 | |||
| 71e36065e5 | |||
| 389d1ba3b9 | |||
| 18f5d4084d | |||
| 83744962f1 | |||
| df08a894cc | |||
| 2354828481 | |||
| 74693bda6f | |||
| 613ff5da71 | |||
| a11937699f | |||
| eb59ca77ef | |||
| 12d07fd870 | |||
| 1d18def642 | |||
| 70d4bce42f | |||
| c81454e00b | |||
| ac4ee2bcf2 | |||
| 9184c119d6 | |||
| 216b114346 | |||
| 793dbdef7e | |||
| 432e1e6065 | |||
| c8a02e1354 | |||
| 698345dbe9 | |||
| 5568073c17 | |||
| addb721d66 | |||
| 3bbf959086 | |||
| 0db4aa5f39 | |||
| f41ee7700d | |||
| 1c335d3172 | |||
| 191b3c09e2 | |||
| 725b4de74a | |||
| ce038bf56a | |||
| 8727038443 | |||
| afbed0e438 | |||
| b6a026da83 | |||
| fc74b723fa | |||
| b1fe1f6073 | |||
| 043ca9a63e | |||
| 46b49eea2f | |||
| 7430eb99cf | |||
| 111cccea97 | |||
| 5e9d87b1ad | |||
| c28b320b66 | |||
| a80a1bbe34 | |||
| c1808ae692 | |||
| d8277e851f | |||
| c795490164 | |||
| 3f2fa717c9 | |||
| c0be2330b0 | |||
| e86467d007 | |||
| e5afd54ce0 | |||
| 25d2af3b04 | |||
| 8e24583f2a | |||
| c09846bb36 | |||
| 86034bd955 | |||
| a9797879e8 | |||
| 407d2bba47 | |||
| 8f4b5ab4c7 | |||
| 0fd203371d | |||
| 68f2d8b925 | |||
| 973c30592f | |||
| 3886ec5291 | |||
| 929775c517 | |||
| 427893efef | |||
| cb33871934 | |||
| 4a86b24ff5 | |||
| 8f98de4abc | |||
| e6460208d3 | |||
| 3b7315d1e2 | |||
| 3aafe54887 | |||
| f08f19cd86 | |||
| 2e6a32b298 | |||
| 57df77a995 | |||
| 343c55f981 | |||
| 1660e0796d | |||
| b30f11ed7a | |||
| 2bdee705b7 | |||
| 31f567f1ef | |||
| 216573b65b | |||
| 4102690cf1 | |||
| a82ac9c50d | |||
| bb0257ccc6 | |||
| 142a70365f | |||
| 12ddf80fe9 | |||
| 34fcca052b | |||
| e06e7aa8f3 | |||
| 4d701be053 | |||
| 3bf02c558c | |||
| e7dcc8dc30 | |||
| b7f197d278 | |||
| 3412a0b7bd | |||
| 23951acdec | |||
| b56bb7f226 | |||
| f0fafe97fe | |||
| 9df360cf63 | |||
| 035ee3a402 | |||
| 035a2554ee | |||
| 4c8f8ff1b6 | |||
| 35cddab3bd | |||
| 0a5f6f2ca7 | |||
| 53253d443c | |||
| 07f2f9c39e | |||
| 1d4026ec71 | |||
| 6524fa3f9c | |||
| 6e24b2681b | |||
| 5ba20268dd | |||
| 4e03759c0f | |||
| a6be3e763f | |||
| 29ac119127 | |||
| 67ce93ffc8 | |||
| 08964f8775 | |||
| d8d2d84aa7 | |||
| 7d69fa3ed5 | |||
| dff7a8976a | |||
| 50fbe55be9 | |||
| 648543e536 | |||
| 3d2654923a | |||
| d03798629c | |||
| e470ac4b0f | |||
| 9324e3511f | |||
| 23d0607239 | |||
| ebba222a86 | |||
| fdbecb2a3f | |||
| 785513914c | |||
| c789853b32 | |||
| 97ec416b3e | |||
| 164c8ad05c | |||
| 7b02026476 | |||
| 1fb26b68c6 | |||
| 29fd8b8805 | |||
| 31b9048144 | |||
| 10c0e04926 | |||
| c0ad3ce1a6 | |||
| 82def1349f | |||
| 94a52aa2db | |||
| 50f65aa698 | |||
| e12314a6fa | |||
| 15e377e678 | |||
| 7b1dab8546 | |||
| 93e9dc5c1e | |||
| 0dcb046576 | |||
| 5288510979 | |||
| 81481832d8 | |||
| 27e704ab80 | |||
| da339a83cd | |||
| 99780d3eb0 | |||
| aee0ec7dec | |||
| b8e8beb62b | |||
| b4ef0ae4f3 | |||
| d9087bf2a9 | |||
| 2f29ee49db | |||
| abc5a58b19 | |||
| 01d7e3a5f2 | |||
| ea08fad2e0 | |||
| a47bbf1e67 | |||
| 1fe38b1b9c | |||
| ed489149dc | |||
| 190d3c4972 | |||
| ea62d01e65 | |||
| 97156c918b | |||
| d79013f1c1 | |||
| b69b221e62 | |||
| 266138dcf2 | |||
| a8299e867d | |||
| 7dc4d653c2 | |||
| 2f9e67e8b2 | |||
| 2c058bcbca | |||
| 528eba2faa | |||
| 7f7c37eeba | |||
| 18adb1f5bd | |||
| a521bc0f54 | |||
| 6f173ffebd | |||
| 7e31cbabe5 | |||
| e8e966b67a | |||
| 73af405400 | |||
| 037723eb90 | |||
| d432bebce8 | |||
| 0a3cffa1a1 | |||
| 796107c4c5 | |||
| fd0df9fe47 | |||
| 58a7f4ea5f | |||
| 725b8d6f8a | |||
| e5a1c1c97e | |||
| b894dbf243 | |||
| 92821c8d81 | |||
| af8360f363 | |||
| 8b12a31f73 | |||
| fd55eb678c | |||
| bb3ce645a4 | |||
| 4e339f1788 | |||
| dca9c7079c | |||
| 52a8909e77 | |||
| 9d2c445bb7 | |||
| 6a1c2fa5dd | |||
| 809c3f3607 | |||
| bebf0df2de | |||
| 5652eb7ee3 | |||
| b6ba8f8555 | |||
| 22bfd44065 | |||
| 3136346a01 | |||
| f536449f0c | |||
| 7659424f28 | |||
| eff40dd907 | |||
| 800af218a5 | |||
| f5c1b6dfdd | |||
| dfdfba5d2f | |||
| 047a483464 | |||
| 4a908e7e14 | |||
| bcf25135a1 | |||
| 087efbe553 | |||
| 2be0ab6474 | |||
| 9a1abfad9c | |||
| f7f119b100 | |||
| bd78f8833f | |||
| 4a081d6fa7 | |||
| 42268e044c | |||
| 48dda32c3e | |||
| a21ed92ac3 | |||
| ee71ae89f7 | |||
| a97377fdea | |||
| 1d4420820f | |||
| 596bc76cc6 | |||
| cc1b80229c | |||
| f07ac48a33 | |||
| 8abfc43fc8 | |||
| 7361d7a220 | |||
| 52d4ddb714 | |||
| ca60b8671c | |||
| 9e0bb80163 | |||
| ce7dcbc163 | |||
| cf93afb639 | |||
| 1119a9e55f | |||
| 51d2213819 | |||
| b567ee55f3 | |||
| 5ef77185a1 | |||
| 4ae8ae7231 | |||
| 2e7cd451ec | |||
| d301694404 | |||
| 752bce589b | |||
| 67c92b3e56 | |||
| d3570df968 | |||
| 261993ea90 | |||
| 0ae29eb5fa | |||
| 87408d4b7b | |||
| 503f723a64 | |||
| 9c72aac255 | |||
| 34a143696f | |||
| de22936ed1 | |||
| 9da9c95c80 | |||
| a7fe4697c5 | |||
| 1d9bced599 | |||
| a854118f19 | |||
| d496ee3031 | |||
| f29dd884f3 | |||
| e1181f756c | |||
| 4ca40fd3bc | |||
| 6483a62a7c | |||
| 83753af944 | |||
| 6f8ae53f0c | |||
| 2f867b75f2 | |||
| ea31e18d98 | |||
| d03af9de05 | |||
| 4013d0c939 | |||
| 3a261d22f5 | |||
| 2314baf0d3 | |||
| c882778583 | |||
| c67e0fee37 | |||
| 863aa4535a | |||
| 86c9ab2ef5 | |||
| 12faa23222 | |||
| 9cd463b22c | |||
| d7ec81ad0a | |||
| 2d3b4f4b91 | |||
| 131574cd3c | |||
| 8b29c612f8 | |||
| 9c67b73472 | |||
| 6b37a9b95c | |||
| 67ac1d9f4b | |||
| 28410eedad | |||
| 0fb182ccb9 | |||
| 7953e36e82 | |||
| 9cea2777d4 | |||
| 46d3591a4f | |||
| 5fc81db0d9 | |||
| fbdca2dcd5 | |||
| afb7825135 | |||
| c2a1ed855b | |||
| 210b5466bb | |||
| 33d5effbdc | |||
| fa5c512aa8 | |||
| c1b2a9aaa7 | |||
| cdef90c2a4 | |||
| 8e80651617 | |||
| 80775b7436 | |||
| 83dcd75cea | |||
| d52ea90cd2 | |||
| cb59153422 | |||
| 89f03e63c7 | |||
| 692f9cb198 | |||
| 455e735da4 | |||
| 4b34ed1f16 | |||
| 08cb39d0af | |||
| 1d851c390c | |||
| a69123ebc1 | |||
| e3e633fce4 | |||
| 09d053c557 | |||
| 3f86919d44 | |||
| 4e7dbd93ed | |||
| 0944c127ac | |||
| 9cc28db732 | |||
| 21d27495f4 | |||
| 36ec2fef60 | |||
| 830a89cfd4 | |||
| c18766a617 | |||
| f1e61b16b1 | |||
| 3a5ed57eff | |||
| a0b1e00321 | |||
| 652f39d86d | |||
| 3372d38b2d | |||
| a3d9149d2a | |||
| 6a2412f5dd | |||
| 3ef40035ad | |||
| 4da04978be | |||
| 0649593116 | |||
| 818405982d | |||
| 7976776399 | |||
| 69eefaf91f | |||
| 7d694194ca | |||
| be49c3843a | |||
| bb04961b41 | |||
| a91b2dcafc | |||
| 7c04a10545 | |||
| 7eaef53c62 | |||
| d6a191a9b1 | |||
| 566eb87b83 | |||
| e4c8a6b72b | |||
| 9d9d530581 | |||
| 00b2ce18c8 | |||
| 72496ad2aa | |||
| d7985ef05d | |||
| 607297bf54 | |||
| 7c65101609 | |||
| 72e9fb1bc3 | |||
| 4099701852 | |||
| 0f0a428142 | |||
| 12584749c8 | |||
| e759db4ed4 | |||
| 7064e85e5a | |||
| 495ca35c1f | |||
| 3c07a690a2 | |||
| 7c808ae356 | |||
| e236b9f1af | |||
| 2585efc540 | |||
| d940bc8f31 | |||
| 2f7b3eec08 | |||
| c8bf454ccc | |||
| e7bd27a2d0 | |||
| 174206ca36 | |||
| 366335a015 | |||
| 9c5cd54264 | |||
| 1e35eeefaa | |||
| c3a812b3cb | |||
| 124712a954 | |||
| 4f6b2aea19 | |||
| ebea0166f1 | |||
| 689c4fc66c | |||
| c50e9a9ed7 | |||
| 23edeefcdc |
@@ -1,2 +1,5 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
RUST_LOG=info
|
||||
RUST_BACKTRACE=1
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Global owners. If you want to set more specific (per-directory, per-language) owners, see the write-up at
|
||||
# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners
|
||||
* @durch @futurechimp @jstuczyn @neacsu
|
||||
@@ -0,0 +1,48 @@
|
||||
name: Continuous integration
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' }}
|
||||
strategy:
|
||||
matrix:
|
||||
rust: [stable, beta, nightly]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ matrix.rust }}
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --all
|
||||
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
if: ${{ matrix.rust != 'nightly' }}
|
||||
with:
|
||||
command: clippy
|
||||
args: -- -D warnings
|
||||
@@ -0,0 +1,14 @@
|
||||
name: Clippy check
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
clippy_check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- run: rustup component add clippy
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features
|
||||
@@ -0,0 +1,44 @@
|
||||
name: Mixnet Contract
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
mixnet-contract:
|
||||
# since it's going to be compiled into wasm, there's absolutely
|
||||
# no point in running CI on different OS-es
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' }}
|
||||
strategy:
|
||||
matrix:
|
||||
rust: [ stable, beta, nightly ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path contracts/mixnet/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --manifest-path contracts/mixnet/Cargo.toml
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path contracts/mixnet/Cargo.toml -- --check
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
if: ${{ matrix.rust != 'nightly' }}
|
||||
with:
|
||||
command: clippy
|
||||
args: --manifest-path contracts/mixnet/Cargo.toml -- -D warnings
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Generate TS types
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
tauri-wallet-types:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: sudo apt-get update && sudo apt-get install -y libpango1.0-dev libatk1.0-dev libgdk-pixbuf2.0-dev libsoup2.4-dev librust-gdk-dev libwebkit2gtk-4.0-dev
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Generate TS
|
||||
run: cd tauri-wallet/src-tauri && cargo test
|
||||
- uses: EndBug/add-and-commit@v7.2.1 # https://github.com/marketplace/actions/add-commit
|
||||
with:
|
||||
add: '["tauri-wallet"]'
|
||||
message: '[ci skip] Generate TS types'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Wasm Client
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
wasm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: test
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path clients/webassembly/Cargo.toml -- --check
|
||||
|
||||
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: clippy
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
/targetString
|
||||
**/*.rs.bk
|
||||
/*/target
|
||||
@@ -22,3 +25,8 @@ v6-topology.json
|
||||
/explorer/downloads/topology.json
|
||||
/explorer/public/downloads/mixmining.json
|
||||
/explorer/public/downloads/topology.json
|
||||
/clients/validator/examples/nym-driver-example/current-contract.txt
|
||||
validator-api/v4.json
|
||||
validator-api/v6.json
|
||||
**/node_modules
|
||||
validator-api/keypair
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: nym
|
||||
Upstream-Contact: Nym Technologies SA <contact@nymtech.net>
|
||||
Source: https://github.com/nymtech/nym
|
||||
|
||||
|
||||
Files: *clients/* *common/* *explorer/*
|
||||
Copyright: 2020, Nym Technologies SA <contact@nymtech.net>
|
||||
License: Apache-2.0
|
||||
@@ -1,15 +0,0 @@
|
||||
language: rust
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
jobs:
|
||||
allow_failures:
|
||||
- rust: nightly
|
||||
fast_finish: true
|
||||
before_script:
|
||||
- rustup component add rustfmt
|
||||
script:
|
||||
- cargo build
|
||||
- cargo test --all
|
||||
- cargo fmt -- --check
|
||||
@@ -1,39 +1,295 @@
|
||||
# Changelog
|
||||
|
||||
## [v0.9.0](https://github.com/nymtech/nym/tree/v0.9.0) (2020-11-13)
|
||||
## [v0.11.0](https://github.com/nymtech/nym/tree/v0.11.0) (2021-07-21)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.8.1...v0.9.0)
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.10.1...v0.11.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Investigate why --clients-host and --mix-host are distinct for gateways [\#435](https://github.com/nymtech/nym/issues/435)
|
||||
- Bugfix/verloc fixes and adjustments [\#618](https://github.com/nymtech/nym/pull/618) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Update the metrics endpoint [\#597](https://github.com/nymtech/nym/issues/597)
|
||||
- Intercontinental problems [\#143](https://github.com/nymtech/nym/issues/143)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Rename `PagedResponse` into `PagedMixnodeResponse` [\#657](https://github.com/nymtech/nym/issues/657)
|
||||
- Change `u64` layer type in contract code [\#648](https://github.com/nymtech/nym/issues/648)
|
||||
- Change `String` types of sphinx and identity keys in contract code [\#647](https://github.com/nymtech/nym/issues/647)
|
||||
- Remove the terrible `decimal_sub_one` once we update contract/validators [\#639](https://github.com/nymtech/nym/issues/639)
|
||||
- After update: failed to receive reply to our echo packet within 1.5s. Stopping the test [\#621](https://github.com/nymtech/nym/issues/621)
|
||||
- update to v0.10.1, it show ERROR message "failed to receive reply to our echo packet within 1.5s" [\#620](https://github.com/nymtech/nym/issues/620)
|
||||
- Make validator client send as much tokens for bonding as required [\#614](https://github.com/nymtech/nym/issues/614)
|
||||
- Update mixnode `init` to not query for entire topology [\#610](https://github.com/nymtech/nym/issues/610)
|
||||
- Potentially extend metrics with number of dropped packets [\#595](https://github.com/nymtech/nym/issues/595)
|
||||
- Delegated staking for gateways [\#579](https://github.com/nymtech/nym/issues/579)
|
||||
- Delegated staking for mixnodes [\#578](https://github.com/nymtech/nym/issues/578)
|
||||
- Improved mixnode and gateway info [\#577](https://github.com/nymtech/nym/issues/577)
|
||||
- Gateway bonding [\#576](https://github.com/nymtech/nym/issues/576)
|
||||
- No graceful degradation on low traffic [\#513](https://github.com/nymtech/nym/issues/513)
|
||||
- Network monitor should not update when 0 packets come back [\#456](https://github.com/nymtech/nym/issues/456)
|
||||
- Add mixnode statistics endpoint [\#406](https://github.com/nymtech/nym/issues/406)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Return the vec instead of the cache wrapper for topology [\#695](https://github.com/nymtech/nym/pull/695) ([neacsu](https://github.com/neacsu))
|
||||
- Updated sign command [\#694](https://github.com/nymtech/nym/pull/694) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- got rid of denomination error in webwallet bonding interface [\#691](https://github.com/nymtech/nym/pull/691) ([mfahampshire](https://github.com/mfahampshire))
|
||||
- Docker testing env [\#687](https://github.com/nymtech/nym/pull/687) ([neacsu](https://github.com/neacsu))
|
||||
- Changed Layer serde behaviour for easier usage [\#686](https://github.com/nymtech/nym/pull/686) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Merge the nym-wallet-web repo into a nym directory [\#684](https://github.com/nymtech/nym/pull/684) ([neacsu](https://github.com/neacsu))
|
||||
- Temporarily using non-cached gateways so we can get our next version … [\#683](https://github.com/nymtech/nym/pull/683) ([futurechimp](https://github.com/futurechimp))
|
||||
- Updating wallet URL in mixnode startup output [\#682](https://github.com/nymtech/nym/pull/682) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/node status api [\#680](https://github.com/nymtech/nym/pull/680) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Using specific commit of rocket cors [\#678](https://github.com/nymtech/nym/pull/678) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Disables nightly clippy CI [\#677](https://github.com/nymtech/nym/pull/677) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Minimize read/write cache contention [\#676](https://github.com/nymtech/nym/pull/676) ([durch](https://github.com/durch))
|
||||
- Feature/validator client upgrade [\#675](https://github.com/nymtech/nym/pull/675) ([futurechimp](https://github.com/futurechimp))
|
||||
- Use cached topology for clients [\#674](https://github.com/nymtech/nym/pull/674) ([neacsu](https://github.com/neacsu))
|
||||
- Use rocket 0.5-rc1, remove rocket-contrib [\#672](https://github.com/nymtech/nym/pull/672) ([durch](https://github.com/durch))
|
||||
- Feature/validator api config [\#671](https://github.com/nymtech/nym/pull/671) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fix a dependabot nag [\#670](https://github.com/nymtech/nym/pull/670) ([durch](https://github.com/durch))
|
||||
- Removed standalone network-monitor [\#669](https://github.com/nymtech/nym/pull/669) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Remove mut where possible, parallel cache requests [\#668](https://github.com/nymtech/nym/pull/668) ([durch](https://github.com/durch))
|
||||
- Rework validator client requests [\#667](https://github.com/nymtech/nym/pull/667) ([durch](https://github.com/durch))
|
||||
- Generalize cache, and cache gateways [\#666](https://github.com/nymtech/nym/pull/666) ([durch](https://github.com/durch))
|
||||
- Validator API server [\#665](https://github.com/nymtech/nym/pull/665) ([durch](https://github.com/durch))
|
||||
- Layer selection [\#664](https://github.com/nymtech/nym/pull/664) ([neacsu](https://github.com/neacsu))
|
||||
- Removing validator binaries, these should go into Github releases [\#663](https://github.com/nymtech/nym/pull/663) ([futurechimp](https://github.com/futurechimp))
|
||||
- Rename network-monitor [\#662](https://github.com/nymtech/nym/pull/662) ([durch](https://github.com/durch))
|
||||
- Adds @neacsu as code owner [\#661](https://github.com/nymtech/nym/pull/661) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/total delegation field [\#660](https://github.com/nymtech/nym/pull/660) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- contracts: Removed mixnode location from the bonding process [\#659](https://github.com/nymtech/nym/pull/659) ([neacsu](https://github.com/neacsu))
|
||||
- Use thiserror for validator-client [\#658](https://github.com/nymtech/nym/pull/658) ([durch](https://github.com/durch))
|
||||
- Feature/configurable verloc http ports [\#656](https://github.com/nymtech/nym/pull/656) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/describe location [\#655](https://github.com/nymtech/nym/pull/655) ([neacsu](https://github.com/neacsu))
|
||||
- Feature/host ip split [\#654](https://github.com/nymtech/nym/pull/654) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/cosmwasm 0.14.1 update [\#653](https://github.com/nymtech/nym/pull/653) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Allow passing optional explicit bond value [\#652](https://github.com/nymtech/nym/pull/652) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Introduced type aliases for mixnode and gateway keys [\#650](https://github.com/nymtech/nym/pull/650) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bugfix/delegation type fixes [\#649](https://github.com/nymtech/nym/pull/649) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Removing the ancient explorer in preparation for a new dawn. [\#645](https://github.com/nymtech/nym/pull/645) ([futurechimp](https://github.com/futurechimp))
|
||||
- Testing code owners again [\#644](https://github.com/nymtech/nym/pull/644) ([futurechimp](https://github.com/futurechimp))
|
||||
- TypeScript client v0.12.0 [\#641](https://github.com/nymtech/nym/pull/641) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/reverse contract mapping [\#640](https://github.com/nymtech/nym/pull/640) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump websockets from 8.1 to 9.1 in /clients/native/examples/python-examples/websocket [\#638](https://github.com/nymtech/nym/pull/638) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Chore/clippy nightly fixes [\#636](https://github.com/nymtech/nym/pull/636) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/delegated staking [\#635](https://github.com/nymtech/nym/pull/635) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump ws from 6.2.1 to 6.2.2 in /clients/validator [\#634](https://github.com/nymtech/nym/pull/634) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump ws from 6.2.1 to 6.2.2 in /clients/native/examples/js-examples/websocket [\#633](https://github.com/nymtech/nym/pull/633) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump ws from 6.2.1 to 6.2.2 in /clients/webassembly/js-example [\#632](https://github.com/nymtech/nym/pull/632) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/stats endpoint [\#631](https://github.com/nymtech/nym/pull/631) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Updated all js related dependencies [\#629](https://github.com/nymtech/nym/pull/629) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/per layer count [\#628](https://github.com/nymtech/nym/pull/628) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Changed rewarding behaviour on not found bonds [\#627](https://github.com/nymtech/nym/pull/627) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump dns-packet from 1.3.1 to 1.3.4 in /clients/native/examples/js-examples/websocket [\#626](https://github.com/nymtech/nym/pull/626) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump dns-packet from 1.3.1 to 1.3.4 in /clients/webassembly/js-example [\#625](https://github.com/nymtech/nym/pull/625) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/update validator binaries [\#624](https://github.com/nymtech/nym/pull/624) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Checking for required bond rather than using hardcoded value [\#623](https://github.com/nymtech/nym/pull/623) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump browserslist from 4.14.1 to 4.16.6 in /clients/native/examples/js-examples/websocket [\#619](https://github.com/nymtech/nym/pull/619) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Changed omitted print to a debug call [\#617](https://github.com/nymtech/nym/pull/617) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.10.1](https://github.com/nymtech/nym/tree/v0.10.1) (2021-05-25)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.10.0...v0.10.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Prometheus metrics doesn't work [\#606](https://github.com/nymtech/nym/issues/606)
|
||||
- Bonding hostname vs. ip-address does not show up on NYM explorer [\#593](https://github.com/nymtech/nym/issues/593)
|
||||
- Cannot assign requested address [\#584](https://github.com/nymtech/nym/issues/584)
|
||||
- Native client upgrade command is broken [\#582](https://github.com/nymtech/nym/issues/582)
|
||||
- Spread directory requests across good validators [\#580](https://github.com/nymtech/nym/issues/580)
|
||||
- Change network monitor to use currency-based rewareds [\#540](https://github.com/nymtech/nym/issues/540)
|
||||
- Unregistration for protocol ipv6 does not work [\#511](https://github.com/nymtech/nym/issues/511)
|
||||
- Network monitor view on validators [\#373](https://github.com/nymtech/nym/issues/373)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Bugfix/unique node ownership [\#612](https://github.com/nymtech/nym/pull/612) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Decreased log severity for verloc-related functionalities [\#611](https://github.com/nymtech/nym/pull/611) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Disabled metrics reporting to the central server [\#609](https://github.com/nymtech/nym/pull/609) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/network monitor gateway pings [\#608](https://github.com/nymtech/nym/pull/608) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Implemented display traits for identity and encryption keys [\#607](https://github.com/nymtech/nym/pull/607) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/add node description api [\#605](https://github.com/nymtech/nym/pull/605) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/updated network monitor [\#604](https://github.com/nymtech/nym/pull/604) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/ping timings [\#603](https://github.com/nymtech/nym/pull/603) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump lodash from 4.17.20 to 4.17.21 in /clients/validator [\#602](https://github.com/nymtech/nym/pull/602) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump lodash from 4.17.20 to 4.17.21 in /clients/native/examples/js-examples/websocket [\#601](https://github.com/nymtech/nym/pull/601) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/add rocket [\#600](https://github.com/nymtech/nym/pull/600) ([futurechimp](https://github.com/futurechimp))
|
||||
- Bump url-parse from 1.4.7 to 1.5.1 in /clients/native/examples/js-examples/websocket [\#599](https://github.com/nymtech/nym/pull/599) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump url-parse from 1.4.7 to 1.5.1 in /clients/webassembly/js-example [\#598](https://github.com/nymtech/nym/pull/598) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Recalculating reward rates on appropriate value changes [\#594](https://github.com/nymtech/nym/pull/594) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Changed default mixnode query page limit [\#592](https://github.com/nymtech/nym/pull/592) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/more exposed client api [\#591](https://github.com/nymtech/nym/pull/591) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Contract adjustment to check for node ownership before allowing bonding [\#590](https://github.com/nymtech/nym/pull/590) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump ssri from 6.0.1 to 6.0.2 in /clients/webassembly/js-example [\#589](https://github.com/nymtech/nym/pull/589) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump ssri from 6.0.1 to 6.0.2 in /clients/native/examples/js-examples/websocket [\#588](https://github.com/nymtech/nym/pull/588) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Impl Error trait for ValidatorClientError [\#587](https://github.com/nymtech/nym/pull/587) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Checking for tx success when sending coins [\#586](https://github.com/nymtech/nym/pull/586) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Logging adjustment [\#585](https://github.com/nymtech/nym/pull/585) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/multiple validator endpoints [\#583](https://github.com/nymtech/nym/pull/583) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Refreshing nodes gets all available nodes from the contract [\#575](https://github.com/nymtech/nym/pull/575) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/simple payments [\#571](https://github.com/nymtech/nym/pull/571) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Minor cosmetic changes while reading around [\#568](https://github.com/nymtech/nym/pull/568) ([huitseeker](https://github.com/huitseeker))
|
||||
|
||||
## [v0.10.0](https://github.com/nymtech/nym/tree/v0.10.0) (2021-04-15)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/validator-client-0.10.0-rc1...v0.10.0)
|
||||
|
||||
This release brings a distributed directory authority powered by [Cosmos SDK](https://cosmos.network) and [CosmWasm](https://cosmwasm.com) smart contracts. It is designed to run [Testnet Finney](https://testnet-finney-explorer.nymtech.net), the new Nym testnet.
|
||||
|
||||
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- When I run this command :'./nym-mixnode run --id zzznym', an error occurs [\#548](https://github.com/nymtech/nym/issues/548)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Displaying address of the client on init [\#573](https://github.com/nymtech/nym/pull/573) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fixed nightly clippy warnings [\#572](https://github.com/nymtech/nym/pull/572) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Changed default client topology refresh rate from 30s to 5min [\#570](https://github.com/nymtech/nym/pull/570) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Adding the wallet url in startup instructions [\#569](https://github.com/nymtech/nym/pull/569) ([futurechimp](https://github.com/futurechimp))
|
||||
- Removed unused data from cargo.toml [\#567](https://github.com/nymtech/nym/pull/567) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/cli signing [\#566](https://github.com/nymtech/nym/pull/566) ([futurechimp](https://github.com/futurechimp))
|
||||
- Updated version number on the validator client [\#565](https://github.com/nymtech/nym/pull/565) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Renamed mixnode registration into bonding [\#564](https://github.com/nymtech/nym/pull/564) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- A pull request for discussion about contract state variables [\#563](https://github.com/nymtech/nym/pull/563) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/mixnet contract ci [\#562](https://github.com/nymtech/nym/pull/562) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/bonding adjustments [\#561](https://github.com/nymtech/nym/pull/561) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/migration additions [\#560](https://github.com/nymtech/nym/pull/560) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Changed default contract execution gas limit to 250\_000 \(from 9\_000\_000\_000\) [\#559](https://github.com/nymtech/nym/pull/559) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Missing quotes in mixnet\_contract\_address config field [\#558](https://github.com/nymtech/nym/pull/558) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Updated default validator url and contract address [\#557](https://github.com/nymtech/nym/pull/557) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bump y18n from 4.0.0 to 4.0.1 in /clients/native/examples/js-examples/websocket [\#556](https://github.com/nymtech/nym/pull/556) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/bonding info on init [\#555](https://github.com/nymtech/nym/pull/555) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator client address getter [\#554](https://github.com/nymtech/nym/pull/554) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Added extra step for publishing validator client [\#553](https://github.com/nymtech/nym/pull/553) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator client rc3 [\#552](https://github.com/nymtech/nym/pull/552) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/upgrade update [\#551](https://github.com/nymtech/nym/pull/551) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/export coin helper [\#550](https://github.com/nymtech/nym/pull/550) ([futurechimp](https://github.com/futurechimp))
|
||||
- Chore/dependency updates [\#549](https://github.com/nymtech/nym/pull/549) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator query client [\#547](https://github.com/nymtech/nym/pull/547) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator client rc2 [\#546](https://github.com/nymtech/nym/pull/546) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/has node query validator client [\#545](https://github.com/nymtech/nym/pull/545) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Added contract query to check if given address owns a mixnode/gateway [\#544](https://github.com/nymtech/nym/pull/544) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [validator-client-0.10.0-rc1](https://github.com/nymtech/nym/tree/validator-client-0.10.0-rc1) (2021-03-24)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.9.2...validator-client-0.10.0-rc1)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Add option to whitelist IPv4 ranges to allowed.list in sphinx-socks [\#415](https://github.com/nymtech/nym/issues/415)
|
||||
- Mixmining monitoring for gateways [\#384](https://github.com/nymtech/nym/issues/384)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Network requester should periodically remove stale proxies [\#424](https://github.com/nymtech/nym/issues/424)
|
||||
- Network requester now prints correct version with --version [\#478](https://github.com/nymtech/nym/pull/478) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Change topology to work with validators. [\#538](https://github.com/nymtech/nym/issues/538)
|
||||
- Unable to rejoin the network after powerdown [\#514](https://github.com/nymtech/nym/issues/514)
|
||||
- nym-socks5-client 0.9.2 issue with outbound\_request\_filter.check [\#498](https://github.com/nymtech/nym/issues/498)
|
||||
- nym-socks5-client high CPU usage on idle [\#491](https://github.com/nymtech/nym/issues/491)
|
||||
- network requester too many Received a 'Send' before 'Connect' - going to buffer the data [\#483](https://github.com/nymtech/nym/issues/483)
|
||||
- Socks5 client loops on malformed - invalidaddress message [\#482](https://github.com/nymtech/nym/issues/482)
|
||||
- Socks5 client hangs [\#479](https://github.com/nymtech/nym/issues/479)
|
||||
- Network Requester -V flag does not print version [\#469](https://github.com/nymtech/nym/issues/469)
|
||||
- Gateway reconnection \(wasm\) [\#458](https://github.com/nymtech/nym/issues/458)
|
||||
- Client warning 'No valid topology' [\#343](https://github.com/nymtech/nym/issues/343)
|
||||
- private key file permission bits too open, readable for others [\#319](https://github.com/nymtech/nym/issues/319)
|
||||
- Fix dependabot security notice [\#267](https://github.com/nymtech/nym/issues/267)
|
||||
- Change how time intervals are serialized in configs [\#141](https://github.com/nymtech/nym/issues/141)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- RC1 published [\#543](https://github.com/nymtech/nym/pull/543) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/prep for publish [\#542](https://github.com/nymtech/nym/pull/542) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/bigger better stronger mnemonics [\#541](https://github.com/nymtech/nym/pull/541) ([futurechimp](https://github.com/futurechimp))
|
||||
- Removed a package-lock.json which seems to have been accidentally added [\#539](https://github.com/nymtech/nym/pull/539) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/convert to uhal [\#537](https://github.com/nymtech/nym/pull/537) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/topology conversion [\#536](https://github.com/nymtech/nym/pull/536) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/hook up url in validator client [\#535](https://github.com/nymtech/nym/pull/535) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/upgrade cosm client [\#534](https://github.com/nymtech/nym/pull/534) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/mix contract identity key [\#533](https://github.com/nymtech/nym/pull/533) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/validator client rust [\#532](https://github.com/nymtech/nym/pull/532) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/add currency helpers [\#531](https://github.com/nymtech/nym/pull/531) ([futurechimp](https://github.com/futurechimp))
|
||||
- Exporting Coin struct, needed for wallet [\#530](https://github.com/nymtech/nym/pull/530) ([futurechimp](https://github.com/futurechimp))
|
||||
- Getting correct user home dir in Python setup script [\#528](https://github.com/nymtech/nym/pull/528) ([futurechimp](https://github.com/futurechimp))
|
||||
- Temporarily disabling fs access [\#527](https://github.com/nymtech/nym/pull/527) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/validator client gateway bonding [\#526](https://github.com/nymtech/nym/pull/526) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fixed eslint errors in the validator client [\#525](https://github.com/nymtech/nym/pull/525) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/gateway bonding [\#524](https://github.com/nymtech/nym/pull/524) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fix the remove mixnode test [\#522](https://github.com/nymtech/nym/pull/522) ([futurechimp](https://github.com/futurechimp))
|
||||
- Bump elliptic from 6.5.3 to 6.5.4 in /clients/native/examples/js-examples/websocket [\#521](https://github.com/nymtech/nym/pull/521) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Feature/fix go errors in examples [\#516](https://github.com/nymtech/nym/pull/516) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/initial mixnet contract [\#515](https://github.com/nymtech/nym/pull/515) ([futurechimp](https://github.com/futurechimp))
|
||||
- Running CI also on windows and macOS [\#512](https://github.com/nymtech/nym/pull/512) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/socks5 adjustments [\#510](https://github.com/nymtech/nym/pull/510) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fixed unused import in non-unix systems [\#509](https://github.com/nymtech/nym/pull/509) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Checking if the delay has already expired before attempting to put it… [\#508](https://github.com/nymtech/nym/pull/508) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Not including gateway non-delay when calculating total packet delay [\#507](https://github.com/nymtech/nym/pull/507) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Allowing for a single topology refresh failure [\#505](https://github.com/nymtech/nym/pull/505) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- More restrictive unix key files permissions [\#504](https://github.com/nymtech/nym/pull/504) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- More human-readable errors on mixnode/gateway startup [\#503](https://github.com/nymtech/nym/pull/503) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/ip filtering [\#502](https://github.com/nymtech/nym/pull/502) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/wasm client compilation fixes [\#501](https://github.com/nymtech/nym/pull/501) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fixed possible crash on invalid topology [\#500](https://github.com/nymtech/nym/pull/500) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/gateway monitoring [\#499](https://github.com/nymtech/nym/pull/499) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/GitHub actions and clippy cleanup [\#493](https://github.com/nymtech/nym/pull/493) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fix typos [\#492](https://github.com/nymtech/nym/pull/492) ([rex4539](https://github.com/rex4539))
|
||||
- Bump ini from 1.3.5 to 1.3.8 in /clients/native/examples/js-examples/websocket [\#490](https://github.com/nymtech/nym/pull/490) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- Bump ini from 1.3.5 to 1.3.8 in /clients/webassembly/js-example [\#489](https://github.com/nymtech/nym/pull/489) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- display 0 on no validators rather than crash [\#488](https://github.com/nymtech/nym/pull/488) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- NGI0 - Updating licensing aspects according REUSE [\#487](https://github.com/nymtech/nym/pull/487) ([lnceballosz](https://github.com/lnceballosz))
|
||||
- Feature/removed topology [\#481](https://github.com/nymtech/nym/pull/481) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bugfix/explorer fixes [\#477](https://github.com/nymtech/nym/pull/477) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/0.9.2+only monitoring [\#475](https://github.com/nymtech/nym/pull/475) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.9.2](https://github.com/nymtech/nym/tree/v0.9.2) (2020-11-26)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.9.1...v0.9.2)
|
||||
|
||||
This release brings networking improvements, eliminating blocking calls and improving mixnode and gateway scalability.
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Putting initial packet onto the queue when establishing connection [\#471](https://github.com/nymtech/nym/pull/471) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Release/v0.9.2 [\#474](https://github.com/nymtech/nym/pull/474) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Minor mixnet client code simplification and optimization [\#472](https://github.com/nymtech/nym/pull/472) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.9.1](https://github.com/nymtech/nym/tree/v0.9.1) (2020-11-24)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.9.0...v0.9.1)
|
||||
|
||||
The main features of this release are:
|
||||
|
||||
* a reputation tracking system which starts to link node reputation to quality of service
|
||||
* a new component, the `nym-network-monitor`, which tracks whether nodes are working properly and providing good service
|
||||
* automatic node registration and de-registration at node startup
|
||||
* working Cosmos validators with a `nym` token
|
||||
* starting to decentralize the old directory server into the validators
|
||||
* a new block explorer at https://testnet-explorer.nymtech.net which looks the same as the old dashboard but is the basis of something much more advanced. It can be run by anyone.
|
||||
* de-coupling metrics collection from directory services to make the system scale better overall
|
||||
* reliability and performance improvements for mixnode networking
|
||||
- explicit `unregister` command for mixnodes
|
||||
- introduced gateway client reconnection in case of obvious network failures
|
||||
- changed network monitor to send at a constant, adjustable, rate
|
||||
- changed the way in which packets are delayed by mixnodes that should reduce number of tasks spawned
|
||||
- changed the way in which packets are forwarded to further mixes that should get rid of possible blocking
|
||||
|
||||
See the changelog for detailed release notes.
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Nicer error if trying to run an uninitialised client/node [\#389](https://github.com/nymtech/nym/issues/389)
|
||||
- Gateway announcement [\#383](https://github.com/nymtech/nym/issues/383)
|
||||
- Add init flag for incentives address [\#382](https://github.com/nymtech/nym/issues/382)
|
||||
- Ed25519 Identity Keys for Mixnodes [\#379](https://github.com/nymtech/nym/issues/379)
|
||||
- Introduce version field to config files [\#375](https://github.com/nymtech/nym/issues/375)
|
||||
- Change `init` to not blow away existing keys \(if exist\) [\#368](https://github.com/nymtech/nym/issues/368)
|
||||
- Introduce an explicit `upgrade` command [\#367](https://github.com/nymtech/nym/issues/367)
|
||||
- Show remote hostname in socks5 connection messages [\#365](https://github.com/nymtech/nym/issues/365)
|
||||
- Make all `const` duration values more explicit. [\#333](https://github.com/nymtech/nym/issues/333)
|
||||
- Change how mix packets get delayed [\#361](https://github.com/nymtech/nym/issues/361)
|
||||
- Feature/socks improvements [\#423](https://github.com/nymtech/nym/pull/423) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/instant sending [\#359](https://github.com/nymtech/nym/pull/359) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- React wasm example not compiling [\#394](https://github.com/nymtech/nym/issues/394)
|
||||
- Update main.js [\#441](https://github.com/nymtech/nym/pull/441) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bugfix/metrics fixes [\#434](https://github.com/nymtech/nym/pull/434) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bugfix/upgrade fix [\#421](https://github.com/nymtech/nym/pull/421) ([jstuczyn](https://github.com/jstuczyn))
|
||||
@@ -42,25 +298,23 @@ See the changelog for detailed release notes.
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Make validator URL configurable [\#438](https://github.com/nymtech/nym/issues/438)
|
||||
- Change default directory location [\#432](https://github.com/nymtech/nym/issues/432)
|
||||
- Crank up the default bandwidth settings. [\#429](https://github.com/nymtech/nym/issues/429)
|
||||
- Change "sphinx-socks" to "nym-requester" [\#428](https://github.com/nymtech/nym/issues/428)
|
||||
- Clients should use only "active" nodes [\#390](https://github.com/nymtech/nym/issues/390)
|
||||
- Allow persistently changing config values from command line [\#387](https://github.com/nymtech/nym/issues/387)
|
||||
- Remove `--config` flag in `run` [\#385](https://github.com/nymtech/nym/issues/385)
|
||||
- Metrics server should return a metrics rate value [\#374](https://github.com/nymtech/nym/issues/374)
|
||||
- Integer staking [\#372](https://github.com/nymtech/nym/issues/372)
|
||||
- Mixnode and gateway blockchain registration [\#371](https://github.com/nymtech/nym/issues/371)
|
||||
- Remove presence notifications [\#370](https://github.com/nymtech/nym/issues/370)
|
||||
- Handle invalid base58 encoding for asymmetric key recovery \(encryption and identity\) [\#285](https://github.com/nymtech/nym/issues/285)
|
||||
- Socks5 nym client + bitcoin service provider [\#254](https://github.com/nymtech/nym/issues/254)
|
||||
- Message reception in webassembly client [\#204](https://github.com/nymtech/nym/issues/204)
|
||||
- Simplest possible staking system [\#157](https://github.com/nymtech/nym/issues/157)
|
||||
- Validator should hold topology [\#77](https://github.com/nymtech/nym/issues/77)
|
||||
- Gateway reconnections \(simple\) [\#457](https://github.com/nymtech/nym/issues/457)
|
||||
- Slow down network monitor sending rate [\#455](https://github.com/nymtech/nym/issues/455)
|
||||
- Deploy the new explorer on the same box as metrics. [\#433](https://github.com/nymtech/nym/issues/433)
|
||||
- Too many open files [\#366](https://github.com/nymtech/nym/issues/366)
|
||||
- nym-mixnode doesn't bind to any port \(Ubuntu 20.04\) [\#290](https://github.com/nymtech/nym/issues/290)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Updated message on shutdown [\#467](https://github.com/nymtech/nym/pull/467) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Additional feedback on unregistration on sigint [\#466](https://github.com/nymtech/nym/pull/466) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/upgrade additions [\#465](https://github.com/nymtech/nym/pull/465) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/nonblocking mix send [\#464](https://github.com/nymtech/nym/pull/464) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/delay queue mixnodes [\#462](https://github.com/nymtech/nym/pull/462) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/slowed down network monitor [\#461](https://github.com/nymtech/nym/pull/461) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/unregister command [\#460](https://github.com/nymtech/nym/pull/460) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Simple gateway client reconnection in obvious network failures [\#459](https://github.com/nymtech/nym/pull/459) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- temporarily disabled mixnode status dot [\#454](https://github.com/nymtech/nym/pull/454) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Removed incentives form url [\#451](https://github.com/nymtech/nym/pull/451) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Removed hardcoded 'good gateways' in favour of pseusorandom choice fr… [\#450](https://github.com/nymtech/nym/pull/450) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Fixed the URL of the websocket [\#449](https://github.com/nymtech/nym/pull/449) ([futurechimp](https://github.com/futurechimp))
|
||||
@@ -108,6 +362,62 @@ See the changelog for detailed release notes.
|
||||
- Added sphinx socks to default workspace members [\#358](https://github.com/nymtech/nym/pull/358) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/wasm update [\#341](https://github.com/nymtech/nym/pull/341) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.9.0](https://github.com/nymtech/nym/tree/v0.9.0) (2020-11-13)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.8.1...v0.9.0)
|
||||
|
||||
The main features of this release are:
|
||||
|
||||
* a reputation tracking system which starts to link node reputation to quality of service
|
||||
* a new component, the `nym-network-monitor`, which tracks whether nodes are working properly and providing good service
|
||||
* automatic node registration and de-registration at node startup
|
||||
* working Cosmos validators with a `nym` token
|
||||
* starting to decentralize the old directory server into the validators
|
||||
* a new block explorer at https://testnet-explorer.nymtech.net which looks the same as the old dashboard but is the basis of something much more advanced. It can be run by anyone.
|
||||
* de-coupling metrics collection from directory services to make the system scale better overall
|
||||
* reliability and performance improvements for mixnode networking
|
||||
|
||||
See the changelog for detailed release notes.
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Nicer error if trying to run an uninitialised client/node [\#389](https://github.com/nymtech/nym/issues/389)
|
||||
- Gateway announcement [\#383](https://github.com/nymtech/nym/issues/383)
|
||||
- Add init flag for incentives address [\#382](https://github.com/nymtech/nym/issues/382)
|
||||
- Ed25519 Identity Keys for Mixnodes [\#379](https://github.com/nymtech/nym/issues/379)
|
||||
- Introduce version field to config files [\#375](https://github.com/nymtech/nym/issues/375)
|
||||
- Change `init` to not blow away existing keys \(if exist\) [\#368](https://github.com/nymtech/nym/issues/368)
|
||||
- Introduce an explicit `upgrade` command [\#367](https://github.com/nymtech/nym/issues/367)
|
||||
- Show remote hostname in socks5 connection messages [\#365](https://github.com/nymtech/nym/issues/365)
|
||||
- Make all `const` duration values more explicit. [\#333](https://github.com/nymtech/nym/issues/333)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- React wasm example not compiling [\#394](https://github.com/nymtech/nym/issues/394)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Make validator URL configurable [\#438](https://github.com/nymtech/nym/issues/438)
|
||||
- Change default directory location [\#432](https://github.com/nymtech/nym/issues/432)
|
||||
- Crank up the default bandwidth settings. [\#429](https://github.com/nymtech/nym/issues/429)
|
||||
- Change "sphinx-socks" to "nym-requester" [\#428](https://github.com/nymtech/nym/issues/428)
|
||||
- Clients should use only "active" nodes [\#390](https://github.com/nymtech/nym/issues/390)
|
||||
- Allow persistently changing config values from command line [\#387](https://github.com/nymtech/nym/issues/387)
|
||||
- Remove `--config` flag in `run` [\#385](https://github.com/nymtech/nym/issues/385)
|
||||
- Metrics server should return a metrics rate value [\#374](https://github.com/nymtech/nym/issues/374)
|
||||
- Integer staking [\#372](https://github.com/nymtech/nym/issues/372)
|
||||
- Mixnode and gateway blockchain registration [\#371](https://github.com/nymtech/nym/issues/371)
|
||||
- Remove presence notifications [\#370](https://github.com/nymtech/nym/issues/370)
|
||||
- Handle invalid base58 encoding for asymmetric key recovery \(encryption and identity\) [\#285](https://github.com/nymtech/nym/issues/285)
|
||||
- Socks5 nym client + bitcoin service provider [\#254](https://github.com/nymtech/nym/issues/254)
|
||||
- Message reception in webassembly client [\#204](https://github.com/nymtech/nym/issues/204)
|
||||
- Simplest possible staking system [\#157](https://github.com/nymtech/nym/issues/157)
|
||||
- Validator should hold topology [\#77](https://github.com/nymtech/nym/issues/77)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Release/v0.9.0 [\#453](https://github.com/nymtech/nym/pull/453) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.8.1](https://github.com/nymtech/nym/tree/v0.8.1) (2020-09-28)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.8.0...v0.8.1)
|
||||
@@ -237,7 +547,7 @@ See the [changelog](https://github.com/nymtech/nym/blob/develop/CHANGELOG.md) fo
|
||||
**Closed issues:**
|
||||
|
||||
- Move to userpubkey@gatewaypubkey addresses. [\#235](https://github.com/nymtech/nym/issues/235)
|
||||
- Get `start\_local\_network.sh` working with the js example [\#227](https://github.com/nymtech/nym/issues/227)
|
||||
- Get `start_local_network.sh` working with the js example [\#227](https://github.com/nymtech/nym/issues/227)
|
||||
- Fix indeterminate test failure [\#218](https://github.com/nymtech/nym/issues/218)
|
||||
- Remove 'fetch' mechanism from desktop client's client in favour of push [\#211](https://github.com/nymtech/nym/issues/211)
|
||||
- Mixnode - load Sphinx keys like Gateway [\#209](https://github.com/nymtech/nym/issues/209)
|
||||
@@ -262,12 +572,12 @@ See the [changelog](https://github.com/nymtech/nym/blob/develop/CHANGELOG.md) fo
|
||||
- Bring health-checker into validator mix-mining [\#78](https://github.com/nymtech/nym/issues/78)
|
||||
- Solidify TCPSocket on client [\#72](https://github.com/nymtech/nym/issues/72)
|
||||
- scripts: run\_local\_network.sh doesn't die nicely [\#45](https://github.com/nymtech/nym/issues/45)
|
||||
- WASM version of the Sphinx packet [\#19](https://github.com/nymtech/nym/issues/19)
|
||||
- Persistent socket connection \(TCP Socket with provider\) [\#18](https://github.com/nymtech/nym/issues/18)
|
||||
- Persistent socket connection \(Websocket with client\) [\#17](https://github.com/nymtech/nym/issues/17)
|
||||
- Persistent socket connection \(TCP Socket with client\) [\#13](https://github.com/nymtech/nym/issues/13)
|
||||
- Persistent socket connection \(Websocket with client\) [\#12](https://github.com/nymtech/nym/issues/12)
|
||||
- Persistently store ledger with registered clients and their auth tokens [\#6](https://github.com/nymtech/nym/issues/6)
|
||||
- Persistent socket connection \(Websocket with client\) [\#17](https://github.com/nymtech/nym/issues/17)
|
||||
- Persistent socket connection \(TCP Socket with provider\) [\#18](https://github.com/nymtech/nym/issues/18)
|
||||
- Persistent socket connection \(Websocket with client\) [\#12](https://github.com/nymtech/nym/issues/12)
|
||||
- Persistent socket connection \(TCP Socket with client\) [\#13](https://github.com/nymtech/nym/issues/13)
|
||||
- WASM version of the Sphinx packet [\#19](https://github.com/nymtech/nym/issues/19)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
@@ -410,11 +720,11 @@ This release fixes bugs in v0.5.0. All testnet node operators are advised to up
|
||||
- Fix incorrectly used Arcs [\#47](https://github.com/nymtech/nym/issues/47)
|
||||
- nym-mixnode mandatory host option [\#26](https://github.com/nymtech/nym/issues/26)
|
||||
- Create config struct for mixnode \(possibly also for client\) [\#21](https://github.com/nymtech/nym/issues/21)
|
||||
- Reuse TCP socket connection between client and mixnodes [\#20](https://github.com/nymtech/nym/issues/20)
|
||||
- Once implementation is available, wherever appropriate, replace `futures::lock::Mutex` with `futures::lock::RwLock` [\#9](https://github.com/nymtech/nym/issues/9)
|
||||
- Check if RwLock on MixProcessingData is still needed [\#8](https://github.com/nymtech/nym/issues/8)
|
||||
- Reuse TCP socket connection between mixnodes and providers [\#3](https://github.com/nymtech/nym/issues/3)
|
||||
- Once implementation is available, wherever appropriate, replace `futures::lock::Mutex` with `futures::lock::RwLock` [\#9](https://github.com/nymtech/nym/issues/9)
|
||||
- Persistent socket connection with other mixes [\#2](https://github.com/nymtech/nym/issues/2)
|
||||
- Reuse TCP socket connection between client and mixnodes [\#20](https://github.com/nymtech/nym/issues/20)
|
||||
- Reuse TCP socket connection between mixnodes and providers [\#3](https://github.com/nymtech/nym/issues/3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
@@ -440,7 +750,6 @@ This release fixes bugs in v0.5.0. All testnet node operators are advised to up
|
||||
**Merged pull requests:**
|
||||
|
||||
- Bugfix/healthcheck on provided topology [\#108](https://github.com/nymtech/nym/pull/108) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/check packet length [\#99](https://github.com/nymtech/nym/pull/99) ([futurechimp](https://github.com/futurechimp))
|
||||
|
||||
## [v0.4.0](https://github.com/nymtech/nym/tree/v0.4.0) (2020-01-28)
|
||||
|
||||
@@ -491,6 +800,7 @@ This release also integrates a health-checker and network topology refresh into
|
||||
- Feature/base58 [\#102](https://github.com/nymtech/nym/pull/102) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/panic improvements [\#101](https://github.com/nymtech/nym/pull/101) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/fix sphinx unwraps [\#100](https://github.com/nymtech/nym/pull/100) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/check packet length [\#99](https://github.com/nymtech/nym/pull/99) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/version filtering improvements [\#96](https://github.com/nymtech/nym/pull/96) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/refreshing topology [\#94](https://github.com/nymtech/nym/pull/94) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/consistent logging [\#93](https://github.com/nymtech/nym/pull/93) ([futurechimp](https://github.com/futurechimp))
|
||||
@@ -514,8 +824,8 @@ This release also integrates a health-checker and network topology refresh into
|
||||
- Messages returned by fetch are base64 encoded [\#55](https://github.com/nymtech/nym/issues/55)
|
||||
- Check layer 1 connectivity at client start [\#38](https://github.com/nymtech/nym/issues/38)
|
||||
- Check required sfw-provider args [\#27](https://github.com/nymtech/nym/issues/27)
|
||||
- Make Electron app work with new Rust mixnet client [\#16](https://github.com/nymtech/nym/issues/16)
|
||||
- Take version numbers into account when picking routes [\#14](https://github.com/nymtech/nym/issues/14)
|
||||
- Make Electron app work with new Rust mixnet client [\#16](https://github.com/nymtech/nym/issues/16)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
@@ -558,7 +868,7 @@ This release also integrates a health-checker and network topology refresh into
|
||||
**Merged pull requests:**
|
||||
|
||||
- Feature/client topology filtering [\#54](https://github.com/nymtech/nym/pull/54) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- print public key for nym client tools [\#53](https://github.com/nymtech/nym/pull/53) ([mileschet](https://github.com/mileschet))
|
||||
- print public key for nym client tools [\#53](https://github.com/nymtech/nym/pull/53) ([ghost](https://github.com/ghost))
|
||||
- Showing binding warning on binding to localhost, 0.0.0.0 or 127.0.0.1 [\#52](https://github.com/nymtech/nym/pull/52) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- validator: moving sample config files into sample configs directory [\#51](https://github.com/nymtech/nym/pull/51) ([futurechimp](https://github.com/futurechimp))
|
||||
- Feature/validator health checker [\#50](https://github.com/nymtech/nym/pull/50) ([jstuczyn](https://github.com/jstuczyn))
|
||||
@@ -581,7 +891,7 @@ This release also integrates a health-checker and network topology refresh into
|
||||
|
||||
## [0.2.0](https://github.com/nymtech/nym/tree/0.2.0) (2020-01-06)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/0.1.0...0.2.0)
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/3c64a2facd753f4f2f431e7f888e54842e2bc64e...0.2.0)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
@@ -8,18 +11,22 @@ panic = "abort"
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"clients/client-core",
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"clients/tauri-client/src-tauri",
|
||||
"clients/webassembly",
|
||||
"clients/client-core",
|
||||
"common/client-libs/gateway-client",
|
||||
"common/client-libs/metrics-client",
|
||||
"common/client-libs/mixnet-client",
|
||||
"common/client-libs/validator-client",
|
||||
"common/coconut-interface",
|
||||
"common/config",
|
||||
"common/credentials",
|
||||
"common/crypto",
|
||||
"common/mixnet-contract",
|
||||
"common/mixnode-common",
|
||||
"common/network-defaults",
|
||||
"common/nonexhaustive-delayqueue",
|
||||
"common/nymsphinx",
|
||||
"common/nymsphinx/acknowledgements",
|
||||
@@ -32,15 +39,16 @@ members = [
|
||||
"common/nymsphinx/params",
|
||||
"common/nymsphinx/types",
|
||||
"common/pemstore",
|
||||
"common/socks5/requests",
|
||||
"common/socks5/proxy-helpers",
|
||||
"common/socks5/requests",
|
||||
"common/topology",
|
||||
"common/wasm-utils",
|
||||
"explorer-api",
|
||||
"gateway",
|
||||
"gateway/gateway-requests",
|
||||
"mixnode",
|
||||
"network-monitor",
|
||||
"service-providers/network-requester",
|
||||
"validator-api",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -50,7 +58,7 @@ default-members = [
|
||||
"gateway",
|
||||
"service-providers/network-requester",
|
||||
"mixnode",
|
||||
"network-monitor",
|
||||
"validator-api",
|
||||
]
|
||||
|
||||
exclude = ["explorer"]
|
||||
exclude = ["explorer", "contracts"]
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
|
||||
4. Limitations and Disclaimers.
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
|
||||
|
||||
Standard License Header
|
||||
|
||||
There is no standard license header for the license
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) <year> <copyright holders>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
Standard License Header
|
||||
|
||||
There is no standard license header for the license
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
<!--
|
||||
Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
## The Nym Privacy Platform
|
||||
|
||||
This repository contains the Nym mixnet.
|
||||
@@ -6,9 +11,15 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
||||
|
||||
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* nym-socks5-client - a Socks5 proxy you can run on your machine, and use with existing applications
|
||||
* nym-gateway - acts sort of like a mailbox for mixnet messages, removing the need for directly delivery to potentially offline or firewalled devices.
|
||||
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* nym-wallet (currently in development)- a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
||||
|
||||
[](https://travis-ci.com/nymtech/nym)
|
||||
|
||||
### Building
|
||||
|
||||
@@ -21,3 +32,8 @@ There's a `.env.sample-dev` file provided which you can rename to `.env` if you
|
||||
### Developer chat
|
||||
|
||||
You can chat to us in [Keybase](https://keybase.io). Download their chat app, then click **Teams -> Join a team**. Type **nymtech.friends** into the team name and hit **continue**. For general chat, hang out in the **#general** channel. Our development takes places in the **#dev** channel. Node operators should be in the **#node-operators** channel.
|
||||
|
||||
### Licensing and copyright information
|
||||
|
||||
This program is available as open source under the terms of the Apache 2.0 license. However, some elements are being licensed under CC0-1.0 and MIT. For accurate information, please check individual files.
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
[package]
|
||||
name = "client-core"
|
||||
version = "0.9.0"
|
||||
version = "0.11.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dirs = "2.0.2"
|
||||
futures = "0.3.1"
|
||||
humantime-serde = "1.0.1"
|
||||
dirs = "3.0"
|
||||
futures = "0.3"
|
||||
humantime-serde = "1.0"
|
||||
log = "0.4"
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
serde = { version = "1.0.104", features = ["derive"] }
|
||||
sled = "0.33"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sled = "0.34"
|
||||
tokio = { version = "1.4", features = ["macros"] }
|
||||
url = { version ="2.2", features = ["serde"] }
|
||||
|
||||
# internal
|
||||
config = { path = "../../common/config" }
|
||||
@@ -28,4 +29,4 @@ topology = { path = "../../common/topology" }
|
||||
validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::mix_traffic::BatchMixMessageSender;
|
||||
use crate::client::topology_control::TopologyAccessor;
|
||||
@@ -46,7 +35,7 @@ where
|
||||
|
||||
/// Internal state, determined by `average_message_sending_delay`,
|
||||
/// used to keep track of when a next packet should be sent out.
|
||||
next_delay: time::Delay,
|
||||
next_delay: Pin<Box<time::Sleep>>,
|
||||
|
||||
/// Channel used for sending prepared sphinx packets to `MixTrafficController` that sends them
|
||||
/// out to the network without any further delays.
|
||||
@@ -74,7 +63,7 @@ where
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
// it is not yet time to return a message
|
||||
if Pin::new(&mut self.next_delay).poll(cx).is_pending() {
|
||||
if self.next_delay.as_mut().poll(cx).is_pending() {
|
||||
return Poll::Pending;
|
||||
};
|
||||
|
||||
@@ -87,7 +76,7 @@ where
|
||||
// The next interval value is `next_poisson_delay` after the one that just
|
||||
// yielded.
|
||||
let next = now + next_poisson_delay;
|
||||
self.next_delay.reset(next);
|
||||
self.next_delay.as_mut().reset(next);
|
||||
|
||||
Poll::Ready(Some(()))
|
||||
}
|
||||
@@ -112,7 +101,7 @@ impl LoopCoverTrafficStream<OsRng> {
|
||||
average_ack_delay,
|
||||
average_packet_delay,
|
||||
average_cover_message_sending_delay,
|
||||
next_delay: time::delay_for(Default::default()),
|
||||
next_delay: Box::pin(time::sleep(Default::default())),
|
||||
mix_tx,
|
||||
our_full_destination,
|
||||
rng,
|
||||
@@ -166,10 +155,10 @@ impl LoopCoverTrafficStream<OsRng> {
|
||||
|
||||
async fn run(&mut self) {
|
||||
// we should set initial delay only when we actually start the stream
|
||||
self.next_delay = time::delay_for(sample_poisson_duration(
|
||||
self.next_delay = Box::pin(time::sleep(sample_poisson_duration(
|
||||
&mut self.rng,
|
||||
self.average_cover_message_sending_delay,
|
||||
));
|
||||
)));
|
||||
|
||||
while self.next().await.is_some() {
|
||||
self.on_new_message().await;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use futures::channel::mpsc;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
|
||||
pub type InputMessageSender = mpsc::UnboundedSender<InputMessage>;
|
||||
pub type InputMessageReceiver = mpsc::UnboundedReceiver<InputMessage>;
|
||||
@@ -13,7 +13,7 @@ pub enum InputMessage {
|
||||
with_reply_surb: bool,
|
||||
},
|
||||
Reply {
|
||||
reply_surb: ReplySURB,
|
||||
reply_surb: ReplySurb,
|
||||
data: Vec<u8>,
|
||||
},
|
||||
}
|
||||
@@ -27,7 +27,7 @@ impl InputMessage {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_reply(reply_surb: ReplySURB, data: Vec<u8>) -> Self {
|
||||
pub fn new_reply(reply_surb: ReplySurb, data: Vec<u8>) -> Self {
|
||||
InputMessage::Reply { reply_surb, data }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
@@ -61,8 +50,8 @@ impl KeyManager {
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
KeyManager {
|
||||
identity_keypair: Arc::new(identity::KeyPair::new_with_rng(rng)),
|
||||
encryption_keypair: Arc::new(encryption::KeyPair::new_with_rng(rng)),
|
||||
identity_keypair: Arc::new(identity::KeyPair::new(rng)),
|
||||
encryption_keypair: Arc::new(encryption::KeyPair::new(rng)),
|
||||
gateway_shared_key: None,
|
||||
ack_key: Arc::new(AckKey::new(rng)),
|
||||
}
|
||||
@@ -72,8 +61,8 @@ impl KeyManager {
|
||||
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
|
||||
#[allow(dead_code)]
|
||||
/// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`].
|
||||
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: SharedKeys) {
|
||||
self.gateway_shared_key = Some(Arc::new(gateway_shared_key))
|
||||
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) {
|
||||
self.gateway_shared_key = Some(gateway_shared_key)
|
||||
}
|
||||
|
||||
/// Loads previously stored keys from the disk.
|
||||
@@ -127,12 +116,12 @@ impl KeyManager {
|
||||
),
|
||||
)?;
|
||||
|
||||
pemstore::store_key(self.ack_key.as_ref(), &client_pathfinder.ack_key())?;
|
||||
pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?;
|
||||
|
||||
match self.gateway_shared_key.as_ref() {
|
||||
None => warn!("No gateway shared key available to store!"),
|
||||
Some(gate_key) => {
|
||||
pemstore::store_key(gate_key.as_ref(), &client_pathfinder.gateway_shared_key())?
|
||||
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,8 +143,7 @@ impl KeyManager {
|
||||
// hence it's up to us to ensure it's called in correct context
|
||||
pub fn gateway_shared_key(&self) -> Arc<SharedKeys> {
|
||||
Arc::clone(
|
||||
&self
|
||||
.gateway_shared_key
|
||||
self.gateway_shared_key
|
||||
.as_ref()
|
||||
.expect("tried to unwrap empty gateway key!"),
|
||||
)
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::action_controller::{Action, ActionSender};
|
||||
use futures::StreamExt;
|
||||
|
||||
@@ -1,35 +1,22 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::PendingAcknowledgement;
|
||||
use crate::client::real_messages_control::acknowledgement_control::RetransmissionRequestSender;
|
||||
use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use nonexhaustive_delayqueue::NonExhaustiveDelayQueue;
|
||||
use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey, TimerError};
|
||||
use nymsphinx::chunking::fragment::FragmentIdentifier;
|
||||
use nymsphinx::Delay as SphinxDelay;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::stream::StreamExt;
|
||||
use tokio::time::delay_queue::{self, Expired};
|
||||
use tokio::time::Error as TimerError;
|
||||
|
||||
pub(crate) type ActionSender = UnboundedSender<Action>;
|
||||
|
||||
// The actual data being sent off as well as potential key to the delay queue
|
||||
type PendingAckEntry = (Arc<PendingAcknowledgement>, Option<delay_queue::Key>);
|
||||
type PendingAckEntry = (Arc<PendingAcknowledgement>, Option<QueueKey>);
|
||||
|
||||
// we can either:
|
||||
// - have a completely new set of packets we just sent and need to create entries for
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::action_controller::{Action, ActionSender};
|
||||
use super::PendingAcknowledgement;
|
||||
@@ -22,7 +11,7 @@ use crate::client::{
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::preparer::MessagePreparer;
|
||||
use nymsphinx::{acknowledgements::AckKey, addressing::clients::Recipient};
|
||||
use rand::{CryptoRng, Rng};
|
||||
@@ -49,6 +38,9 @@ impl<R> InputMessageListener<R>
|
||||
where
|
||||
R: CryptoRng + Rng,
|
||||
{
|
||||
// at this point I'm not entirely sure how to deal with this warning without
|
||||
// some considerable refactoring
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(super) fn new(
|
||||
ack_key: Arc<AckKey>,
|
||||
ack_recipient: Recipient,
|
||||
@@ -72,7 +64,7 @@ where
|
||||
}
|
||||
|
||||
// we require topology for replies to generate surb_acks
|
||||
async fn handle_reply(&mut self, reply_surb: ReplySURB, data: Vec<u8>) -> Option<RealMessage> {
|
||||
async fn handle_reply(&mut self, reply_surb: ReplySurb, data: Vec<u8>) -> Option<RealMessage> {
|
||||
let topology_permit = self.topology_access.get_read_permit().await;
|
||||
let topology = match topology_permit.try_get_valid_topology_ref(&self.ack_recipient, None) {
|
||||
Some(topology_ref) => topology_ref,
|
||||
@@ -107,7 +99,7 @@ where
|
||||
recipient: Recipient,
|
||||
content: Vec<u8>,
|
||||
with_reply_surb: bool,
|
||||
) -> Vec<RealMessage> {
|
||||
) -> Option<Vec<RealMessage>> {
|
||||
let topology_permit = self.topology_access.get_read_permit().await;
|
||||
let topology = match topology_permit
|
||||
.try_get_valid_topology_ref(&self.ack_recipient, Some(&recipient))
|
||||
@@ -115,7 +107,7 @@ where
|
||||
Some(topology_ref) => topology_ref,
|
||||
None => {
|
||||
warn!("Could not process the message - the network topology is invalid");
|
||||
return Vec::new();
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -161,7 +153,7 @@ where
|
||||
.unbounded_send(Action::new_insert(pending_acks))
|
||||
.unwrap();
|
||||
|
||||
real_messages
|
||||
Some(real_messages)
|
||||
}
|
||||
|
||||
async fn on_input_message(&mut self, msg: InputMessage) {
|
||||
@@ -174,19 +166,19 @@ where
|
||||
self.handle_fresh_message(recipient, data, with_reply_surb)
|
||||
.await
|
||||
}
|
||||
InputMessage::Reply { reply_surb, data } => {
|
||||
if let Some(real_message) = self.handle_reply(reply_surb, data).await {
|
||||
vec![real_message]
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
InputMessage::Reply { reply_surb, data } => self
|
||||
.handle_reply(reply_surb, data)
|
||||
.await
|
||||
.map(|message| vec![message]),
|
||||
};
|
||||
|
||||
// tells real message sender (with the poisson timer) to send this to the mix network
|
||||
self.real_message_sender
|
||||
.unbounded_send(real_messages)
|
||||
.unwrap();
|
||||
// there's no point in trying to send nothing
|
||||
if let Some(real_messages) = real_messages {
|
||||
// tells real message sender (with the poisson timer) to send this to the mix network
|
||||
self.real_message_sender
|
||||
.unbounded_send(real_messages)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn run(&mut self) {
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use self::{
|
||||
acknowledgement_listener::AcknowledgementListener, action_controller::ActionController,
|
||||
@@ -24,7 +13,6 @@ use crate::client::{inbound_messages::InputMessageReceiver, topology_control::To
|
||||
use futures::channel::mpsc;
|
||||
use gateway_client::AcknowledgementReceiver;
|
||||
use log::*;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use nymsphinx::{
|
||||
acknowledgements::AckKey,
|
||||
addressing::clients::Recipient,
|
||||
@@ -56,7 +44,7 @@ type RetransmissionRequestReceiver = mpsc::UnboundedReceiver<Weak<PendingAcknowl
|
||||
pub(super) type SentPacketNotificationSender = mpsc::UnboundedSender<FragmentIdentifier>;
|
||||
|
||||
/// Channel used for receiving signals about the particular `Fragment` (associated with the `FragmentIdentifier`)
|
||||
/// that it is about to be sent to tbe mix network and its timeout timer should be started.
|
||||
/// that it is about to be sent to the mix network and its timeout timer should be started.
|
||||
type SentPacketNotificationReceiver = mpsc::UnboundedReceiver<FragmentIdentifier>;
|
||||
|
||||
/// Structure representing a data `Fragment` that is on-route to the specified `Recipient`
|
||||
@@ -131,14 +119,6 @@ pub(super) struct Config {
|
||||
|
||||
/// Average delay a data packet is going to get delayed at a single mixnode.
|
||||
average_packet_delay: Duration,
|
||||
|
||||
/// Mode of all mix packets created - VPN or Mix. They indicate whether packets should get delayed
|
||||
/// and keys reused.
|
||||
packet_mode: PacketMode,
|
||||
|
||||
/// If the mode of the client is set to VPN it specifies number of packets created with the
|
||||
/// same initial secret until it gets rotated.
|
||||
vpn_key_reuse_limit: Option<usize>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -147,16 +127,12 @@ impl Config {
|
||||
ack_wait_multiplier: f64,
|
||||
average_ack_delay: Duration,
|
||||
average_packet_delay: Duration,
|
||||
packet_mode: PacketMode,
|
||||
vpn_key_reuse_limit: Option<usize>,
|
||||
) -> Self {
|
||||
Config {
|
||||
ack_wait_addition,
|
||||
ack_wait_multiplier,
|
||||
average_ack_delay,
|
||||
average_packet_delay,
|
||||
packet_mode,
|
||||
vpn_key_reuse_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,8 +173,6 @@ where
|
||||
ack_recipient,
|
||||
config.average_packet_delay,
|
||||
config.average_ack_delay,
|
||||
config.packet_mode,
|
||||
config.vpn_key_reuse_limit,
|
||||
);
|
||||
|
||||
// will listen for any acks coming from the network
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::action_controller::{Action, ActionSender};
|
||||
use super::PendingAcknowledgement;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::action_controller::{Action, ActionSender};
|
||||
use super::SentPacketNotificationReceiver;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// INPUT: InputMessage from user
|
||||
// INPUT2: Acks from mix
|
||||
@@ -30,7 +19,6 @@ use gateway_client::AcknowledgementReceiver;
|
||||
use log::*;
|
||||
use nymsphinx::acknowledgements::AckKey;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use rand::{rngs::OsRng, CryptoRng, Rng};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -62,14 +50,6 @@ pub struct Config {
|
||||
|
||||
/// Average delay an acknowledgement packet is going to get delayed at a single mixnode.
|
||||
average_ack_delay_duration: Duration,
|
||||
|
||||
/// Mode of all mix packets created - VPN or Mix. They indicate whether packets should get delayed
|
||||
/// and keys reused.
|
||||
packet_mode: PacketMode,
|
||||
|
||||
/// If the mode of the client is set to VPN it specifies number of packets created with the
|
||||
/// same initial secret until it gets rotated.
|
||||
vpn_key_reuse_limit: Option<usize>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -81,19 +61,15 @@ impl Config {
|
||||
average_message_sending_delay: Duration,
|
||||
average_packet_delay_duration: Duration,
|
||||
self_recipient: Recipient,
|
||||
packet_mode: PacketMode,
|
||||
vpn_key_reuse_limit: Option<usize>,
|
||||
) -> Self {
|
||||
Config {
|
||||
ack_key,
|
||||
ack_wait_addition,
|
||||
ack_wait_multiplier,
|
||||
self_recipient,
|
||||
average_message_sending_delay,
|
||||
average_packet_delay_duration,
|
||||
average_ack_delay_duration,
|
||||
average_message_sending_delay,
|
||||
ack_wait_multiplier,
|
||||
ack_wait_addition,
|
||||
packet_mode,
|
||||
vpn_key_reuse_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,8 +110,6 @@ impl RealMessagesController<OsRng> {
|
||||
config.ack_wait_multiplier,
|
||||
config.average_ack_delay_duration,
|
||||
config.average_packet_delay_duration,
|
||||
config.packet_mode,
|
||||
config.vpn_key_reuse_limit,
|
||||
);
|
||||
|
||||
let ack_control = AcknowledgementController::new(
|
||||
@@ -171,7 +145,7 @@ impl RealMessagesController<OsRng> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn run(&mut self, vpn_mode: bool) {
|
||||
pub(super) async fn run(&mut self) {
|
||||
let mut out_queue_control = self.out_queue_control.take().unwrap();
|
||||
let mut ack_control = self.ack_control.take().unwrap();
|
||||
|
||||
@@ -179,7 +153,7 @@ impl RealMessagesController<OsRng> {
|
||||
// the task to ever finish. This will of course change once we introduce
|
||||
// graceful shutdowns.
|
||||
let out_queue_control_fut = tokio::spawn(async move {
|
||||
out_queue_control.run_out_queue_control(vpn_mode).await;
|
||||
out_queue_control.run_out_queue_control().await;
|
||||
error!("The out queue controller has finished execution!");
|
||||
out_queue_control
|
||||
});
|
||||
@@ -198,9 +172,9 @@ impl RealMessagesController<OsRng> {
|
||||
|
||||
// &Handle is only passed for consistency sake with other client modules, but I think
|
||||
// when we get to refactoring, we should apply gateway approach and make it implicit
|
||||
pub fn start(mut self, handle: &Handle, vpn_mode: bool) -> JoinHandle<Self> {
|
||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<Self> {
|
||||
handle.spawn(async move {
|
||||
self.run(vpn_mode).await;
|
||||
self.run().await;
|
||||
self
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::mix_traffic::BatchMixMessageSender;
|
||||
use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender;
|
||||
@@ -73,7 +62,7 @@ where
|
||||
|
||||
/// Internal state, determined by `average_message_sending_delay`,
|
||||
/// used to keep track of when a next packet should be sent out.
|
||||
next_delay: time::Delay,
|
||||
next_delay: Pin<Box<time::Sleep>>,
|
||||
|
||||
/// Channel used for sending prepared sphinx packets to `MixTrafficController` that sends them
|
||||
/// out to the network without any further delays.
|
||||
@@ -117,7 +106,7 @@ type BatchRealMessageReceiver = mpsc::UnboundedReceiver<Vec<RealMessage>>;
|
||||
|
||||
pub(crate) enum StreamMessage {
|
||||
Cover,
|
||||
Real(RealMessage),
|
||||
Real(Box<RealMessage>),
|
||||
}
|
||||
|
||||
impl<R> Stream for OutQueueControl<R>
|
||||
@@ -128,7 +117,7 @@ where
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
// it is not yet time to return a message
|
||||
if Pin::new(&mut self.next_delay).poll(cx).is_pending() {
|
||||
if self.next_delay.as_mut().poll(cx).is_pending() {
|
||||
return Poll::Pending;
|
||||
};
|
||||
|
||||
@@ -141,11 +130,11 @@ where
|
||||
// The next interval value is `next_poisson_delay` after the one that just
|
||||
// yielded.
|
||||
let next = now + next_poisson_delay;
|
||||
self.next_delay.reset(next);
|
||||
self.next_delay.as_mut().reset(next);
|
||||
|
||||
// check if we have anything immediately available
|
||||
if let Some(real_available) = self.received_buffer.pop_front() {
|
||||
return Poll::Ready(Some(StreamMessage::Real(real_available)));
|
||||
return Poll::Ready(Some(StreamMessage::Real(Box::new(real_available))));
|
||||
}
|
||||
|
||||
// decide what kind of message to send
|
||||
@@ -158,9 +147,9 @@ where
|
||||
Poll::Ready(Some(real_messages)) => {
|
||||
self.received_buffer = real_messages.into();
|
||||
// we MUST HAVE received at least ONE message
|
||||
Poll::Ready(Some(StreamMessage::Real(
|
||||
Poll::Ready(Some(StreamMessage::Real(Box::new(
|
||||
self.received_buffer.pop_front().unwrap(),
|
||||
)))
|
||||
))))
|
||||
}
|
||||
|
||||
// otherwise construct a dummy one
|
||||
@@ -173,6 +162,9 @@ impl<R> OutQueueControl<R>
|
||||
where
|
||||
R: CryptoRng + Rng + Unpin,
|
||||
{
|
||||
// at this point I'm not entirely sure how to deal with this warning without
|
||||
// some considerable refactoring
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
config: Config,
|
||||
ack_key: Arc<AckKey>,
|
||||
@@ -187,7 +179,7 @@ where
|
||||
config,
|
||||
ack_key,
|
||||
sent_notifier,
|
||||
next_delay: time::delay_for(Default::default()),
|
||||
next_delay: Box::pin(time::sleep(Default::default())),
|
||||
mix_tx,
|
||||
real_receiver,
|
||||
our_full_destination,
|
||||
@@ -257,42 +249,21 @@ where
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
|
||||
async fn on_batch_received(&mut self, real_messages: Vec<RealMessage>) {
|
||||
let mut mix_packets = Vec::with_capacity(real_messages.len());
|
||||
for real_message in real_messages.into_iter() {
|
||||
self.sent_notify(real_message.fragment_id);
|
||||
mix_packets.push(real_message.mix_packet);
|
||||
}
|
||||
self.mix_tx.unbounded_send(mix_packets).unwrap();
|
||||
}
|
||||
|
||||
// Send messages at certain rate and if no real traffic is available, send cover message.
|
||||
async fn run_normal_out_queue(&mut self) {
|
||||
// we should set initial delay only when we actually start the stream
|
||||
self.next_delay = time::delay_for(sample_poisson_duration(
|
||||
self.next_delay = Box::pin(time::sleep(sample_poisson_duration(
|
||||
&mut self.rng,
|
||||
self.config.average_message_sending_delay,
|
||||
));
|
||||
)));
|
||||
|
||||
while let Some(next_message) = self.next().await {
|
||||
self.on_message(next_message).await;
|
||||
}
|
||||
}
|
||||
|
||||
// Send real message as soon as it's available and don't inject ANY cover traffic.
|
||||
async fn run_vpn_out_queue(&mut self) {
|
||||
while let Some(next_messages) = self.real_receiver.next().await {
|
||||
self.on_batch_received(next_messages).await
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run_out_queue_control(&mut self, vpn_mode: bool) {
|
||||
if vpn_mode {
|
||||
debug!("Starting out queue controller in vpn mode...");
|
||||
self.run_vpn_out_queue().await
|
||||
} else {
|
||||
debug!("Starting out queue controller...");
|
||||
self.run_normal_out_queue().await
|
||||
}
|
||||
pub(crate) async fn run_out_queue_control(&mut self) {
|
||||
debug!("Starting out queue controller...");
|
||||
self.run_normal_out_queue().await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::reply_key_storage::ReplyKeyStorage;
|
||||
use crypto::asymmetric::encryption;
|
||||
@@ -21,8 +10,8 @@ use futures::lock::Mutex;
|
||||
use futures::StreamExt;
|
||||
use gateway_client::MixnetMessageReceiver;
|
||||
use log::*;
|
||||
use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SURBEncryptionKey};
|
||||
use nymsphinx::params::{ReplySURBEncryptionAlgorithm, ReplySURBKeyDigestAlgorithm};
|
||||
use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SurbEncryptionKey};
|
||||
use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm};
|
||||
use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
@@ -165,7 +154,7 @@ impl ReceivedMessagesBuffer {
|
||||
|
||||
// while we're at it, also empty the buffer if we happened to receive anything while
|
||||
// no sender was connected
|
||||
let stored_messages = std::mem::replace(&mut guard.messages, Vec::new());
|
||||
let stored_messages = std::mem::take(&mut guard.messages);
|
||||
if !stored_messages.is_empty() {
|
||||
if let Err(err) = sender.unbounded_send(stored_messages) {
|
||||
error!(
|
||||
@@ -191,12 +180,12 @@ impl ReceivedMessagesBuffer {
|
||||
|
||||
fn process_received_reply(
|
||||
reply_ciphertext: &[u8],
|
||||
reply_key: SURBEncryptionKey,
|
||||
reply_key: SurbEncryptionKey,
|
||||
) -> Option<ReconstructedMessage> {
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySURBEncryptionAlgorithm>();
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySurbEncryptionAlgorithm>();
|
||||
|
||||
let mut reply_msg = stream_cipher::decrypt::<ReplySURBEncryptionAlgorithm>(
|
||||
&reply_key.inner(),
|
||||
let mut reply_msg = stream_cipher::decrypt::<ReplySurbEncryptionAlgorithm>(
|
||||
reply_key.inner(),
|
||||
&zero_iv,
|
||||
reply_ciphertext,
|
||||
);
|
||||
@@ -221,7 +210,7 @@ impl ReceivedMessagesBuffer {
|
||||
let mut completed_messages = Vec::new();
|
||||
let mut inner_guard = self.inner.lock().await;
|
||||
|
||||
let reply_surb_digest_size = ReplySURBKeyDigestAlgorithm::output_size();
|
||||
let reply_surb_digest_size = ReplySurbKeyDigestAlgorithm::output_size();
|
||||
|
||||
// first check if this is a reply or a chunked message
|
||||
// TODO: verify with @AP if this way of doing it is safe or whether it could
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use log::*;
|
||||
use nymsphinx::anonymous_replies::{
|
||||
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SURBEncryptionKey,
|
||||
SURBEncryptionKeySize,
|
||||
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SurbEncryptionKey,
|
||||
SurbEncryptionKeySize,
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
@@ -29,7 +18,7 @@ pub enum ReplyKeyStorageError {
|
||||
/// Permanent storage for keys in all sent [`ReplySURB`]
|
||||
///
|
||||
/// Each sent out [`ReplySURB`] has a new key associated with it that is going to be used for
|
||||
/// payload encryption. In order to decrypt whatever reply we receive, we need to know which
|
||||
/// payload encryption. In order to -decrypt whatever reply we receive, we need to know which
|
||||
/// key to use for that purpose. We do it based on received `H(t)` which has to be included
|
||||
/// with each reply.
|
||||
/// Moreover, there is no restriction when the [`ReplySURB`] might get used so we need to
|
||||
@@ -49,24 +38,24 @@ impl ReplyKeyStorage {
|
||||
Ok(ReplyKeyStorage { db })
|
||||
}
|
||||
|
||||
fn read_encryption_key(&self, raw_key: sled::IVec) -> SURBEncryptionKey {
|
||||
fn read_encryption_key(&self, raw_key: sled::IVec) -> SurbEncryptionKey {
|
||||
let key_bytes_ref = raw_key.as_ref();
|
||||
// if this fails it means we have some database corruption and we
|
||||
// absolutely can't continue
|
||||
|
||||
if key_bytes_ref.len() != SURBEncryptionKeySize::to_usize() {
|
||||
if key_bytes_ref.len() != SurbEncryptionKeySize::to_usize() {
|
||||
error!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
||||
panic!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
||||
}
|
||||
|
||||
// this can only fail if the bytes have invalid length but we already asserted it
|
||||
SURBEncryptionKey::try_from_bytes(key_bytes_ref).unwrap()
|
||||
SurbEncryptionKey::try_from_bytes(key_bytes_ref).unwrap()
|
||||
}
|
||||
|
||||
// TOOD: perhaps we could also store some part of original message here too?
|
||||
pub fn insert_encryption_key(
|
||||
&mut self,
|
||||
encryption_key: SURBEncryptionKey,
|
||||
encryption_key: SurbEncryptionKey,
|
||||
) -> Result<(), ReplyKeyStorageError> {
|
||||
let digest = encryption_key.compute_digest();
|
||||
|
||||
@@ -89,7 +78,7 @@ impl ReplyKeyStorage {
|
||||
pub fn get_and_remove_encryption_key(
|
||||
&self,
|
||||
key_digest: EncryptionKeyDigest,
|
||||
) -> Result<Option<SURBEncryptionKey>, ReplyKeyStorageError> {
|
||||
) -> Result<Option<SurbEncryptionKey>, ReplyKeyStorageError> {
|
||||
let removal_result = match self.db.remove(&key_digest.to_vec()) {
|
||||
Err(e) => Err(ReplyKeyStorageError::DbReadError(e)),
|
||||
Ok(existing_key) => {
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::params::DEFAULT_NUM_MIX_HOPS;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::time;
|
||||
@@ -22,7 +13,8 @@ use std::time::Duration;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
use tokio::task::JoinHandle;
|
||||
use topology::NymTopology;
|
||||
use topology::{nym_topology_from_bonds, NymTopology};
|
||||
use url::Url;
|
||||
|
||||
// I'm extremely curious why compiler NEVER complained about lack of Debug here before
|
||||
#[derive(Debug)]
|
||||
@@ -71,9 +63,9 @@ impl<'a> TopologyReadPermit<'a> {
|
||||
Some(topology_ref) => {
|
||||
// see if it's possible to route the packet to both gateways
|
||||
if !topology_ref.can_construct_path_through(DEFAULT_NUM_MIX_HOPS)
|
||||
|| !topology_ref.gateway_exists(&ack_recipient.gateway())
|
||||
|| !topology_ref.gateway_exists(ack_recipient.gateway())
|
||||
|| if let Some(packet_recipient) = packet_recipient {
|
||||
!topology_ref.gateway_exists(&packet_recipient.gateway())
|
||||
!topology_ref.gateway_exists(packet_recipient.gateway())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -129,58 +121,108 @@ impl TopologyAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TopologyAccessor {
|
||||
fn default() -> Self {
|
||||
TopologyAccessor::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TopologyRefresherConfig {
|
||||
directory_server: String,
|
||||
validator_api_urls: Vec<Url>,
|
||||
refresh_rate: time::Duration,
|
||||
}
|
||||
|
||||
impl TopologyRefresherConfig {
|
||||
pub fn new(directory_server: String, refresh_rate: time::Duration) -> Self {
|
||||
pub fn new(validator_api_urls: Vec<Url>, refresh_rate: time::Duration) -> Self {
|
||||
TopologyRefresherConfig {
|
||||
directory_server,
|
||||
validator_api_urls,
|
||||
refresh_rate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TopologyRefresher {
|
||||
validator_client: validator_client::Client,
|
||||
validator_client: validator_client::ApiClient,
|
||||
|
||||
validator_api_urls: Vec<Url>,
|
||||
topology_accessor: TopologyAccessor,
|
||||
refresh_rate: Duration,
|
||||
|
||||
currently_used_api: usize,
|
||||
was_latest_valid: bool,
|
||||
}
|
||||
|
||||
impl TopologyRefresher {
|
||||
pub fn new_directory_client(
|
||||
cfg: TopologyRefresherConfig,
|
||||
topology_accessor: TopologyAccessor,
|
||||
) -> Self {
|
||||
let validator_client_config = validator_client::Config::new(cfg.directory_server);
|
||||
let validator_client = validator_client::Client::new(validator_client_config);
|
||||
pub fn new(mut cfg: TopologyRefresherConfig, topology_accessor: TopologyAccessor) -> Self {
|
||||
cfg.validator_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
TopologyRefresher {
|
||||
validator_client,
|
||||
validator_client: validator_client::ApiClient::new(cfg.validator_api_urls[0].clone()),
|
||||
validator_api_urls: cfg.validator_api_urls,
|
||||
topology_accessor,
|
||||
refresh_rate: cfg.refresh_rate,
|
||||
currently_used_api: 0,
|
||||
was_latest_valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(&self) -> Option<NymTopology> {
|
||||
match self.validator_client.get_active_topology().await {
|
||||
Err(err) => {
|
||||
error!("failed to get active network topology! - {:?}", err);
|
||||
None
|
||||
}
|
||||
Ok(topology) => {
|
||||
let nym_topology: NymTopology = topology.into();
|
||||
Some(nym_topology.filter_system_version(env!("CARGO_PKG_VERSION")))
|
||||
}
|
||||
fn use_next_validator_api(&mut self) {
|
||||
if self.validator_api_urls.len() == 1 {
|
||||
warn!("There's only a single validator API available - it won't be possible to use a different one");
|
||||
return;
|
||||
}
|
||||
|
||||
self.currently_used_api = (self.currently_used_api + 1) % self.validator_api_urls.len();
|
||||
self.validator_client
|
||||
.change_validator_api(self.validator_api_urls[self.currently_used_api].clone())
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
||||
// TODO: optimization for the future:
|
||||
// only refresh mixnodes on timer and refresh gateways only when
|
||||
// we have to send to a new, unknown, gateway
|
||||
|
||||
let mixnodes = match self.validator_client.get_cached_mixnodes().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network mixnodes - {}", err);
|
||||
return None;
|
||||
}
|
||||
Ok(mixes) => mixes,
|
||||
};
|
||||
|
||||
let gateways = match self.validator_client.get_cached_gateways().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network gateways - {}", err);
|
||||
return None;
|
||||
}
|
||||
Ok(gateways) => gateways,
|
||||
};
|
||||
|
||||
let topology = nym_topology_from_bonds(mixnodes, gateways);
|
||||
|
||||
// TODO: I didn't want to change it now, but the expected system version should rather be put in config
|
||||
// rather than pulled from package version of `client_core`
|
||||
Some(topology.filter_system_version(env!("CARGO_PKG_VERSION")))
|
||||
}
|
||||
|
||||
pub async fn refresh(&mut self) {
|
||||
trace!("Refreshing the topology");
|
||||
let new_topology = self.get_current_compatible_topology().await;
|
||||
|
||||
if new_topology.is_none() {
|
||||
self.use_next_validator_api();
|
||||
}
|
||||
|
||||
if new_topology.is_none() && self.was_latest_valid {
|
||||
// if we failed to grab this topology, but the one before it was alright, let's assume
|
||||
// validator had a tiny hiccup and use the old data
|
||||
warn!("we're going to keep on using the old topology for this iteration");
|
||||
self.was_latest_valid = false;
|
||||
return;
|
||||
} else if new_topology.is_some() {
|
||||
self.was_latest_valid = true;
|
||||
}
|
||||
|
||||
self.topology_accessor
|
||||
.update_global_topology(new_topology)
|
||||
.await;
|
||||
@@ -193,7 +235,7 @@ impl TopologyRefresher {
|
||||
pub fn start(mut self, handle: &Handle) -> JoinHandle<()> {
|
||||
handle.spawn(async move {
|
||||
loop {
|
||||
tokio::time::delay_for(self.refresh_rate).await;
|
||||
tokio::time::sleep(self.refresh_rate).await;
|
||||
self.refresh().await;
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,33 +1,18 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use config::defaults::*;
|
||||
use config::NymConfig;
|
||||
use serde::{
|
||||
de::{self, IntoDeserializer, Visitor},
|
||||
Deserialize, Deserializer, Serialize,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
pub mod persistence;
|
||||
|
||||
pub const MISSING_VALUE: &str = "MISSING VALUE";
|
||||
|
||||
// 'CLIENT'
|
||||
pub const DEFAULT_VALIDATOR_REST_ENDPOINT: &str = "http://testnet-validator1.nymtech.net:8081";
|
||||
|
||||
// 'DEBUG'
|
||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||
|
||||
@@ -35,59 +20,9 @@ const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
|
||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_millis(30_000);
|
||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_VPN_KEY_REUSE_LIMIT: usize = 1000;
|
||||
|
||||
const ZERO_DELAY: Duration = Duration::from_nanos(0);
|
||||
|
||||
// custom function is defined to deserialize based on whether field contains a pre 0.9.0
|
||||
// u64 interpreted as milliseconds or proper duration introduced in 0.9.0
|
||||
//
|
||||
// TODO: when we get to refactoring down the line, this code can just be removed
|
||||
// and all Duration fields could just have #[serde(with = "humantime_serde")] instead
|
||||
// reason for that is that we don't expect anyone to be upgrading from pre 0.9.0 when we have,
|
||||
// for argument sake, 0.11.0 out
|
||||
fn deserialize_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct DurationVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for DurationVisitor {
|
||||
type Value = Duration;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
formatter.write_str("u64 or a duration")
|
||||
}
|
||||
|
||||
fn visit_i64<E>(self, value: i64) -> Result<Duration, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
self.visit_u64(value as u64)
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, value: u64) -> Result<Duration, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Duration::from_millis(Deserialize::deserialize(
|
||||
value.into_deserializer(),
|
||||
)?))
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Duration, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
humantime_serde::deserialize(value.into_deserializer())
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(DurationVisitor)
|
||||
}
|
||||
|
||||
pub fn missing_string_value() -> String {
|
||||
MISSING_VALUE.to_string()
|
||||
@@ -176,24 +111,16 @@ impl<T: NymConfig> Config<T> {
|
||||
self.client.gateway_listener = gateway_listener.into();
|
||||
}
|
||||
|
||||
pub fn set_custom_validator<S: Into<String>>(&mut self, validator: S) {
|
||||
self.client.validator_rest_url = validator.into();
|
||||
pub fn set_custom_validator_apis(&mut self, validator_api_urls: Vec<Url>) {
|
||||
self.client.validator_api_urls = validator_api_urls;
|
||||
}
|
||||
|
||||
pub fn set_high_default_traffic_volume(&mut self) {
|
||||
self.debug.average_packet_delay = Duration::from_millis(1);
|
||||
self.debug.average_packet_delay = Duration::from_millis(10);
|
||||
self.debug.loop_cover_traffic_average_delay = Duration::from_millis(2000000); // basically don't really send cover messages
|
||||
self.debug.message_sending_average_delay = Duration::from_millis(4); // 250 "real" messages / s
|
||||
}
|
||||
|
||||
pub fn set_vpn_mode(&mut self, vpn_mode: bool) {
|
||||
self.client.vpn_mode = vpn_mode;
|
||||
}
|
||||
|
||||
pub fn set_vpn_key_reuse_limit(&mut self, reuse_limit: usize) {
|
||||
self.debug.vpn_key_reuse_limit = Some(reuse_limit)
|
||||
}
|
||||
|
||||
pub fn set_custom_version(&mut self, version: &str) {
|
||||
self.client.version = version.to_string();
|
||||
}
|
||||
@@ -234,8 +161,8 @@ impl<T: NymConfig> Config<T> {
|
||||
self.client.ack_key_file.clone()
|
||||
}
|
||||
|
||||
pub fn get_validator_rest_endpoint(&self) -> String {
|
||||
self.client.validator_rest_url.clone()
|
||||
pub fn get_validator_api_endpoints(&self) -> Vec<Url> {
|
||||
self.client.validator_api_urls.clone()
|
||||
}
|
||||
|
||||
pub fn get_gateway_id(&self) -> String {
|
||||
@@ -248,19 +175,11 @@ impl<T: NymConfig> Config<T> {
|
||||
|
||||
// Debug getters
|
||||
pub fn get_average_packet_delay(&self) -> Duration {
|
||||
if self.client.vpn_mode {
|
||||
ZERO_DELAY
|
||||
} else {
|
||||
self.debug.average_packet_delay
|
||||
}
|
||||
self.debug.average_packet_delay
|
||||
}
|
||||
|
||||
pub fn get_average_ack_delay(&self) -> Duration {
|
||||
if self.client.vpn_mode {
|
||||
ZERO_DELAY
|
||||
} else {
|
||||
self.debug.average_ack_delay
|
||||
}
|
||||
self.debug.average_ack_delay
|
||||
}
|
||||
|
||||
pub fn get_ack_wait_multiplier(&self) -> f64 {
|
||||
@@ -276,11 +195,7 @@ impl<T: NymConfig> Config<T> {
|
||||
}
|
||||
|
||||
pub fn get_message_sending_average_delay(&self) -> Duration {
|
||||
if self.client.vpn_mode {
|
||||
ZERO_DELAY
|
||||
} else {
|
||||
self.debug.message_sending_average_delay
|
||||
}
|
||||
self.debug.message_sending_average_delay
|
||||
}
|
||||
|
||||
pub fn get_gateway_response_timeout(&self) -> Duration {
|
||||
@@ -295,21 +210,6 @@ impl<T: NymConfig> Config<T> {
|
||||
self.debug.topology_resolution_timeout
|
||||
}
|
||||
|
||||
pub fn get_vpn_mode(&self) -> bool {
|
||||
self.client.vpn_mode
|
||||
}
|
||||
|
||||
pub fn get_vpn_key_reuse_limit(&self) -> Option<usize> {
|
||||
match self.get_vpn_mode() {
|
||||
false => None,
|
||||
true => Some(
|
||||
self.debug
|
||||
.vpn_key_reuse_limit
|
||||
.unwrap_or_else(|| DEFAULT_VPN_KEY_REUSE_LIMIT),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_version(&self) -> &str {
|
||||
&self.client.version
|
||||
}
|
||||
@@ -334,15 +234,8 @@ pub struct Client<T> {
|
||||
/// ID specifies the human readable ID of this particular client.
|
||||
id: String,
|
||||
|
||||
/// URL to the validator server for obtaining network topology.
|
||||
#[serde(default = "missing_string_value")]
|
||||
validator_rest_url: String,
|
||||
|
||||
/// Special mode of the system such that all messages are sent as soon as they are received
|
||||
/// and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
/// 'Debug' values will have no effect.
|
||||
#[serde(default)]
|
||||
vpn_mode: bool,
|
||||
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
validator_api_urls: Vec<Url>,
|
||||
|
||||
/// Path to file containing private identity key.
|
||||
private_identity_key_file: PathBuf,
|
||||
@@ -389,8 +282,7 @@ impl<T: NymConfig> Default for Client<T> {
|
||||
Client {
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
id: "".to_string(),
|
||||
validator_rest_url: DEFAULT_VALIDATOR_REST_ENDPOINT.to_string(),
|
||||
vpn_mode: false,
|
||||
validator_api_urls: default_api_endpoints(),
|
||||
private_identity_key_file: Default::default(),
|
||||
public_identity_key_file: Default::default(),
|
||||
private_encryption_key_file: Default::default(),
|
||||
@@ -408,31 +300,31 @@ impl<T: NymConfig> Default for Client<T> {
|
||||
|
||||
impl<T: NymConfig> Client<T> {
|
||||
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("private_identity.pem")
|
||||
T::default_data_directory(Some(id)).join("private_identity.pem")
|
||||
}
|
||||
|
||||
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("public_identity.pem")
|
||||
T::default_data_directory(Some(id)).join("public_identity.pem")
|
||||
}
|
||||
|
||||
fn default_private_encryption_key_file(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("private_encryption.pem")
|
||||
T::default_data_directory(Some(id)).join("private_encryption.pem")
|
||||
}
|
||||
|
||||
fn default_public_encryption_key_file(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("public_encryption.pem")
|
||||
T::default_data_directory(Some(id)).join("public_encryption.pem")
|
||||
}
|
||||
|
||||
fn default_gateway_shared_key_file(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("gateway_shared.pem")
|
||||
T::default_data_directory(Some(id)).join("gateway_shared.pem")
|
||||
}
|
||||
|
||||
fn default_ack_key_file(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("ack_key.pem")
|
||||
T::default_data_directory(Some(id)).join("ack_key.pem")
|
||||
}
|
||||
|
||||
fn default_reply_encryption_key_store_path(id: &str) -> PathBuf {
|
||||
T::default_data_directory(id).join("reply_key_store")
|
||||
T::default_data_directory(Some(id)).join("reply_key_store")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,20 +345,14 @@ pub struct Debug {
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
average_packet_delay: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
average_ack_delay: Duration,
|
||||
|
||||
/// Value multiplied with the expected round trip time of an acknowledgement packet before
|
||||
@@ -477,58 +363,36 @@ pub struct Debug {
|
||||
/// Value added to the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 0.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
ack_wait_addition: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
loop_cover_traffic_average_delay: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take another 'real traffic stream' message to be sent.
|
||||
/// If no real packets are available and cover traffic is enabled,
|
||||
/// a loop cover message is sent instead in order to preserve the rate.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
message_sending_average_delay: Duration,
|
||||
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
gateway_response_timeout: Duration,
|
||||
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
topology_refresh_rate: Duration,
|
||||
|
||||
/// During topology refresh, test packets are sent through every single possible network
|
||||
/// path. This timeout determines waiting period until it is decided that the packet
|
||||
/// did not reach its destination.
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_duration",
|
||||
serialize_with = "humantime_serde::serialize"
|
||||
)]
|
||||
#[serde(with = "humantime_serde")]
|
||||
topology_resolution_timeout: Duration,
|
||||
|
||||
/// If the mode of the client is set to VPN it specifies number of packets created with the
|
||||
/// same initial secret until it gets rotated.
|
||||
vpn_key_reuse_limit: Option<usize>,
|
||||
}
|
||||
|
||||
impl Default for Debug {
|
||||
@@ -543,7 +407,6 @@ impl Default for Debug {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
vpn_key_reuse_limit: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::Config;
|
||||
use config::NymConfig;
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod key_pathfinder;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "0.9.0"
|
||||
version = "0.11.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -16,18 +16,18 @@ futures = "0.3" # bunch of futures stuff, however, now that I think about it, it
|
||||
# the AsyncRead, AsyncWrite, Stream, Sink, etc. traits could be used from tokio
|
||||
# channels should really be replaced with crossbeam due to that implementation being more efficient
|
||||
# and the single instance of abortable we have should really be refactored anyway
|
||||
url = "2.1" # I think we should just replace it with String
|
||||
url = "2.2"
|
||||
|
||||
clap = "2.33.0" # for the command line arguments
|
||||
dirs = "3.0" # for determining default store directories in config
|
||||
dotenv = "0.15.0" # for obtaining environmental variables (only used for RUST_LOG for time being)
|
||||
log = "0.4" # self explanatory
|
||||
pretty_env_logger = "0.3" # for formatting log messages
|
||||
pretty_env_logger = "0.4" # for formatting log messages
|
||||
rand = {version = "0.7.3", features = ["wasm-bindgen"]} # rng-related traits + some rng implementation to use
|
||||
serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization
|
||||
sled = "0.33" # for storage of replySURB decryption keys
|
||||
tokio = { version = "0.2", features = ["full"] } # async runtime
|
||||
tokio-tungstenite = "0.11.0" # websocket
|
||||
sled = "0.34" # for storage of replySURB decryption keys
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal"] } # async runtime
|
||||
tokio-tungstenite = "0.14" # websocket
|
||||
|
||||
## internal
|
||||
client-core = { path = "../client-core" }
|
||||
@@ -43,4 +43,4 @@ validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
version-checker = { path = "../../common/version-checker" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0" # for the "textsend" example
|
||||
serde_json = "1.0" # for the "textsend" example
|
||||
|
||||
@@ -9,21 +9,21 @@ import (
|
||||
)
|
||||
|
||||
// request tags
|
||||
const SEND_REQUEST_TAG = 0x00
|
||||
const REPLY_REQUEST_TAG = 0x01
|
||||
const SELF_ADDRESS_REQUEST_TAG = 0x02
|
||||
const sendRequestTag = 0x00
|
||||
const replyRequestTag = 0x01
|
||||
const selfAddressRequestTag = 0x02
|
||||
|
||||
// response tags
|
||||
const ERROR_RESPONSE_TAG = 0x00
|
||||
const RECEIVED_RESPONSE_TAG = 0x01
|
||||
const SELF_ADDRESS_RESPONSE_TAG = 0x02
|
||||
const errorResponseTag = 0x00
|
||||
const receivedResponseTag = 0x01
|
||||
const selfAddressResponseTag = 0x02
|
||||
|
||||
func makeSelfAddressRequest() []byte {
|
||||
return []byte{SELF_ADDRESS_REQUEST_TAG}
|
||||
return []byte{selfAddressRequestTag}
|
||||
}
|
||||
|
||||
func parseSelfAddressResponse(rawResponse []byte) []byte {
|
||||
if len(rawResponse) != 97 || rawResponse[0] != SELF_ADDRESS_RESPONSE_TAG {
|
||||
if len(rawResponse) != 97 || rawResponse[0] != selfAddressResponseTag {
|
||||
panic("Received invalid response")
|
||||
}
|
||||
return rawResponse[1:]
|
||||
@@ -38,7 +38,7 @@ func makeSendRequest(recipient []byte, message []byte, withReplySurb bool) []byt
|
||||
surbByte = 1
|
||||
}
|
||||
|
||||
out := []byte{SEND_REQUEST_TAG, surbByte}
|
||||
out := []byte{sendRequestTag, surbByte}
|
||||
out = append(out, recipient...)
|
||||
out = append(out, messageLen...)
|
||||
out = append(out, message...)
|
||||
@@ -53,7 +53,7 @@ func makeReplyRequest(message []byte, replySURB []byte) []byte {
|
||||
surbLen := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(surbLen, uint64(len(replySURB)))
|
||||
|
||||
out := []byte{REPLY_REQUEST_TAG}
|
||||
out := []byte{replyRequestTag}
|
||||
out = append(out, surbLen...)
|
||||
out = append(out, replySURB...)
|
||||
out = append(out, messageLen...)
|
||||
@@ -63,7 +63,7 @@ func makeReplyRequest(message []byte, replySURB []byte) []byte {
|
||||
}
|
||||
|
||||
func parseReceived(rawResponse []byte) ([]byte, []byte) {
|
||||
if rawResponse[0] != RECEIVED_RESPONSE_TAG {
|
||||
if rawResponse[0] != receivedResponseTag {
|
||||
panic("Received invalid response!")
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func parseReceived(rawResponse []byte) ([]byte, []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func sendWithoutReply() {
|
||||
func sendBinaryWithoutReply() {
|
||||
uri := "ws://localhost:1977"
|
||||
|
||||
conn, _, err := websocket.DefaultDialer.Dial(uri, nil)
|
||||
@@ -122,12 +122,12 @@ func sendWithoutReply() {
|
||||
}
|
||||
selfAddress := parseSelfAddressResponse(receivedResponse)
|
||||
|
||||
read_data, err := ioutil.ReadFile("dummy_file")
|
||||
readData, err := ioutil.ReadFile("dummy_file")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sendRequest := makeSendRequest(selfAddress, read_data, false)
|
||||
sendRequest := makeSendRequest(selfAddress, readData, false)
|
||||
fmt.Printf("sending content of 'dummy file' over the mix network...\n")
|
||||
if err = conn.WriteMessage(websocket.BinaryMessage, sendRequest); err != nil {
|
||||
panic(err)
|
||||
@@ -144,10 +144,10 @@ func sendWithoutReply() {
|
||||
panic("did not expect a replySURB!")
|
||||
}
|
||||
fmt.Printf("writing the file back to the disk!\n")
|
||||
ioutil.WriteFile("received_file_noreply", fileData, 0644)
|
||||
ioutil.WriteFile("received_file_no_reply", fileData, 0644)
|
||||
}
|
||||
|
||||
func sendWithReply() {
|
||||
func sendBinaryWithReply() {
|
||||
uri := "ws://localhost:1977"
|
||||
|
||||
conn, _, err := websocket.DefaultDialer.Dial(uri, nil)
|
||||
@@ -212,6 +212,6 @@ func sendWithReply() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// sendWithoutReply()
|
||||
sendWithReply()
|
||||
// sendBinaryWithoutReply()
|
||||
sendBinaryWithReply()
|
||||
}
|
||||
@@ -4,5 +4,5 @@ go 1.14
|
||||
|
||||
require (
|
||||
github.com/btcsuite/btcutil v1.0.2 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis efficitur neque. Quisque aliquet vulputate ante, eget vehicula odio feugiat ac. Nulla ut mattis magna. Aenean tincidunt quis nulla eget eleifend. Cras in pretium sem. Nunc lorem metus, blandit sit amet egestas ut, feugiat quis tellus. Aenean tristique, enim a tincidunt condimentum, eros est blandit nunc, id viverra metus erat at nulla. Vivamus at tellus sodales, feugiat odio vel, laoreet neque. Vivamus posuere nulla ac sodales bibendum.
|
||||
|
||||
Vestibulum pulvinar nisi non ultricies egestas. Integer finibus ultrices justo vitae suscipit. Etiam interdum eu justo vel interdum. Morbi sagittis ac nisl quis consequat. Mauris dapibus ut risus ac facilisis. Pellentesque non tortor feugiat, consectetur arcu vel, ullamcorper sapien. Proin sodales purus non orci bibendum, sit amet ultrices justo ullamcorper. Nullam ac risus ac justo ultricies efficitur auctor nec arcu. Etiam sed finibus felis. Suspendisse potenti. Phasellus malesuada velit ac ullamcorper egestas. Sed elementum diam ut est gravida ultricies.
|
||||
|
||||
Pellentesque sed metus massa. Cras imperdiet lacus sit amet dolor aliquam, luctus posuere justo hendrerit. Morbi augue ex, gravida a metus sed, scelerisque euismod lacus. Nam consequat sapien ac pellentesque sagittis. Morbi a ultrices massa, vel aliquet ex. Maecenas ac sem diam. Nunc sed erat et ipsum volutpat auctor. Etiam elit felis, commodo vitae ipsum ac, fermentum lobortis arcu. Aliquam eu tempus enim. Curabitur vulputate imperdiet aliquam. Morbi iaculis rhoncus risus at malesuada. Donec accumsan feugiat ligula ut facilisis. Nunc porttitor sit amet est eget malesuada. Sed sed consectetur augue, non dapibus orci. Mauris aliquam pellentesque quam, sit amet pellentesque velit cursus vitae. Morbi sit amet molestie risus.
|
||||
|
||||
Nam gravida non ligula a egestas. Fusce sodales, purus id rhoncus mattis, purus est vehicula urna, vel finibus augue velit et est. Donec dictum erat eleifend lobortis iaculis. Praesent id venenatis ante. Donec feugiat, ipsum eget porttitor pulvinar, nisl odio posuere lorem, ut placerat elit nulla a ligula. Suspendisse nec nibh tincidunt, sollicitudin mi a, volutpat ligula. In maximus quam lacus, eget semper dolor sagittis sit amet.
|
||||
|
||||
In vitae hendrerit est, quis facilisis dui. In eu ante enim. Nullam hendrerit odio sit amet odio tincidunt eleifend. Aliquam erat volutpat. Curabitur commodo, purus pharetra lobortis rhoncus, tortor massa imperdiet nisl, vel dignissim tortor sem at orci. Aliquam maximus lobortis lacus, eu porttitor purus dapibus ut. Praesent at dapibus felis, efficitur blandit tortor. In hac habitasse platea dictumst. Aenean ultrices, nisl a pretium sagittis, tellus sapien mollis erat, eu consectetur erat mauris sed libero. Duis feugiat dapibus mi, vel ornare velit vehicula mattis. Ut suscipit pharetra leo et sollicitudin.
|
||||
@@ -26,7 +26,7 @@ func getSelfAddress(conn *websocket.Conn) string {
|
||||
return responseJSON["address"].(string)
|
||||
}
|
||||
|
||||
func sendWithoutReply() {
|
||||
func sendTextWithoutReply() {
|
||||
message := "Hello Nym!"
|
||||
|
||||
uri := "ws://localhost:1977"
|
||||
@@ -62,7 +62,7 @@ func sendWithoutReply() {
|
||||
fmt.Printf("received %v from the mix network!\n", string(receivedMessage))
|
||||
}
|
||||
|
||||
func sendWithReply() {
|
||||
func sendTextWithReply() {
|
||||
message := "Hello Nym!"
|
||||
|
||||
uri := "ws://localhost:1977"
|
||||
@@ -97,13 +97,13 @@ func sendWithReply() {
|
||||
}
|
||||
fmt.Printf("received %v from the mix network!\n", string(receivedMessage))
|
||||
|
||||
receivedMessageJson := make(map[string]interface{})
|
||||
if err := json.Unmarshal(receivedMessage, &receivedMessageJson); err != nil {
|
||||
receivedMessageJSON := make(map[string]interface{})
|
||||
if err := json.Unmarshal(receivedMessage, &receivedMessageJSON); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// use the received surb to send an anonymous reply!
|
||||
replySurb := receivedMessageJson["replySurb"]
|
||||
replySurb := receivedMessageJSON["replySurb"]
|
||||
replyMessage := "hello from reply SURB!"
|
||||
|
||||
reply, err := json.Marshal(map[string]interface{}{
|
||||
@@ -129,6 +129,6 @@ func sendWithReply() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// sendWithoutReply()
|
||||
sendWithReply()
|
||||
// sendTextWithoutReply()
|
||||
sendTextWithReply()
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
"author": "Dave Hrycyszyn",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.8.0",
|
||||
"autoprefixer": "^10.2.6",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"webpack": "^4.42.1",
|
||||
"webpack-cli": "^3.3.11",
|
||||
|
||||
@@ -36,31 +36,42 @@
|
||||
},
|
||||
"websockets": {
|
||||
"hashes": [
|
||||
"sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5",
|
||||
"sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5",
|
||||
"sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308",
|
||||
"sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb",
|
||||
"sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a",
|
||||
"sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c",
|
||||
"sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170",
|
||||
"sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422",
|
||||
"sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8",
|
||||
"sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485",
|
||||
"sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f",
|
||||
"sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8",
|
||||
"sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc",
|
||||
"sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779",
|
||||
"sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989",
|
||||
"sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1",
|
||||
"sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092",
|
||||
"sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824",
|
||||
"sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d",
|
||||
"sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55",
|
||||
"sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36",
|
||||
"sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b"
|
||||
"sha256:0dd4eb8e0bbf365d6f652711ce21b8fd2b596f873d32aabb0fbb53ec604418cc",
|
||||
"sha256:1d0971cc7251aeff955aa742ec541ee8aaea4bb2ebf0245748fbec62f744a37e",
|
||||
"sha256:1d6b4fddb12ab9adf87b843cd4316c4bd602db8d5efd2fb83147f0458fe85135",
|
||||
"sha256:230a3506df6b5f446fed2398e58dcaafdff12d67fe1397dff196411a9e820d02",
|
||||
"sha256:276d2339ebf0df4f45df453923ebd2270b87900eda5dfd4a6b0cfa15f82111c3",
|
||||
"sha256:2cf04601633a4ec176b9cc3d3e73789c037641001dbfaf7c411f89cd3e04fcaf",
|
||||
"sha256:3ddff38894c7857c476feb3538dd847514379d6dc844961dc99f04b0384b1b1b",
|
||||
"sha256:48c222feb3ced18f3dc61168ca18952a22fb88e5eb8902d2bf1b50faefdc34a2",
|
||||
"sha256:51d04df04ed9d08077d10ccbe21e6805791b78eac49d16d30a1f1fe2e44ba0af",
|
||||
"sha256:597c28f3aa7a09e8c070a86b03107094ee5cdafcc0d55f2f2eac92faac8dc67d",
|
||||
"sha256:5c8f0d82ea2468282e08b0cf5307f3ad022290ed50c45d5cb7767957ca782880",
|
||||
"sha256:7189e51955f9268b2bdd6cc537e0faa06f8fffda7fb386e5922c6391de51b077",
|
||||
"sha256:7df3596838b2a0c07c6f6d67752c53859a54993d4f062689fdf547cb56d0f84f",
|
||||
"sha256:826ccf85d4514609219725ba4a7abd569228c2c9f1968e8be05be366f68291ec",
|
||||
"sha256:836d14eb53b500fd92bd5db2fc5894f7c72b634f9c2a28f546f75967503d8e25",
|
||||
"sha256:85db8090ba94e22d964498a47fdd933b8875a1add6ebc514c7ac8703eb97bbf0",
|
||||
"sha256:85e701a6c316b7067f1e8675c638036a796fe5116783a4c932e7eb8e305a3ffe",
|
||||
"sha256:900589e19200be76dd7cbaa95e9771605b5ce3f62512d039fb3bc5da9014912a",
|
||||
"sha256:9147868bb0cc01e6846606cd65cbf9c58598f187b96d14dd1ca17338b08793bb",
|
||||
"sha256:9e7fdc775fe7403dbd8bc883ba59576a6232eac96dacb56512daacf7af5d618d",
|
||||
"sha256:ab5ee15d3462198c794c49ccd31773d8a2b8c17d622aa184f669d2b98c2f0857",
|
||||
"sha256:ad893d889bc700a5835e0a95a3e4f2c39e91577ab232a3dc03c262a0f8fc4b5c",
|
||||
"sha256:b2e71c4670ebe1067fa8632f0d081e47254ee2d3d409de54168b43b0ba9147e0",
|
||||
"sha256:b43b13e5622c5a53ab12f3272e6f42f1ce37cd5b6684b2676cb365403295cd40",
|
||||
"sha256:b4ad84b156cf50529b8ac5cc1638c2cf8680490e3fccb6121316c8c02620a2e4",
|
||||
"sha256:be5fd35e99970518547edc906efab29afd392319f020c3c58b0e1a158e16ed20",
|
||||
"sha256:caa68c95bc1776d3521f81eeb4d5b9438be92514ec2a79fececda814099c8314",
|
||||
"sha256:d144b350045c53c8ff09aa1cfa955012dd32f00c7e0862c199edcabb1a8b32da",
|
||||
"sha256:d2c2d9b24d3c65b5a02cac12cbb4e4194e590314519ed49db2f67ef561c3cf58",
|
||||
"sha256:e9e5fd6dbdf95d99bc03732ded1fc8ef22ebbc05999ac7e0c7bf57fe6e4e5ae2",
|
||||
"sha256:ebf459a1c069f9866d8569439c06193c586e72c9330db1390af7c6a0a32c4afd",
|
||||
"sha256:f31722f1c033c198aa4a39a01905951c00bd1c74f922e8afc1b1c62adbcdd56a",
|
||||
"sha256:f68c352a68e5fdf1e97288d5cec9296664c590c25932a8476224124aaf90dbcd"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==8.1"
|
||||
"version": "==9.1"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message, WebSocketStream};
|
||||
use tokio_tungstenite::{
|
||||
connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream,
|
||||
};
|
||||
use websocket_requests::{requests::ClientRequest, responses::ServerResponse};
|
||||
|
||||
// just helpers functions that work in this very particular context because we are sending to ourselves
|
||||
// and hence will always get a response back (i.e. the message we sent)
|
||||
async fn send_message_and_get_response(
|
||||
ws_stream: &mut WebSocketStream<TcpStream>,
|
||||
ws_stream: &mut WebSocketStream<MaybeTlsStream<TcpStream>>,
|
||||
req: Vec<u8>,
|
||||
) -> ServerResponse {
|
||||
ws_stream.send(Message::Binary(req)).await.unwrap();
|
||||
@@ -18,7 +20,7 @@ async fn send_message_and_get_response(
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_self_address(ws_stream: &mut WebSocketStream<TcpStream>) -> Recipient {
|
||||
async fn get_self_address(ws_stream: &mut WebSocketStream<MaybeTlsStream<TcpStream>>) -> Recipient {
|
||||
let self_address_request = ClientRequest::SelfAddress.serialize();
|
||||
let response = send_message_and_get_response(ws_stream, self_address_request).await;
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use serde_json::json;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message, WebSocketStream};
|
||||
use tokio_tungstenite::{
|
||||
connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream,
|
||||
};
|
||||
|
||||
// PREFACE: in practice I don't see why you would ever want to use text api while in Rust, but example
|
||||
// is here for the completion sake
|
||||
@@ -9,7 +11,7 @@ use tokio_tungstenite::{connect_async, tungstenite::protocol::Message, WebSocket
|
||||
// just helpers functions that work in this very particular context because we are sending to ourselves
|
||||
// and hence will always get a response back (i.e. the message we sent)
|
||||
async fn send_message_and_get_json_response(
|
||||
ws_stream: &mut WebSocketStream<TcpStream>,
|
||||
ws_stream: &mut WebSocketStream<MaybeTlsStream<TcpStream>>,
|
||||
text_req: String,
|
||||
) -> serde_json::Value {
|
||||
ws_stream.send(Message::Text(text_req)).await.unwrap();
|
||||
@@ -20,7 +22,7 @@ async fn send_message_and_get_json_response(
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_self_address(ws_stream: &mut WebSocketStream<TcpStream>) -> String {
|
||||
async fn get_self_address(ws_stream: &mut WebSocketStream<MaybeTlsStream<TcpStream>>) -> String {
|
||||
let self_address_request = json!({ "type": "selfAddress" }).to_string();
|
||||
let response = send_message_and_get_json_response(ws_stream, self_address_request).await;
|
||||
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::template::config_template;
|
||||
use client_core::config::Config as BaseConfig;
|
||||
pub use client_core::config::MISSING_VALUE;
|
||||
use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
use config::NymConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod template;
|
||||
|
||||
const DEFAULT_LISTENING_PORT: u16 = 1977;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize, Clone, Copy)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub enum SocketType {
|
||||
@@ -128,7 +116,7 @@ impl Default for Socket {
|
||||
fn default() -> Self {
|
||||
Socket {
|
||||
socket_type: SocketType::WebSocket,
|
||||
listening_port: DEFAULT_LISTENING_PORT,
|
||||
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,11 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub(crate) fn config_template() -> &'static str {
|
||||
// While using normal toml marshalling would have been way simpler with less overhead,
|
||||
// I think it's useful to have comments attached to the saved config file to explain behaviour of
|
||||
// particular fields.
|
||||
// Note: any changes to the template must be reflected in the appropriate structs in mod.rs.
|
||||
// Note: any changes to the template must be reflected in the appropriate structs in verloc.
|
||||
r#"
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
@@ -30,13 +19,12 @@ version = '{{ client.version }}'
|
||||
# Human readable ID of this particular client.
|
||||
id = '{{ client.id }}'
|
||||
|
||||
# URL to the validator server for obtaining network topology.
|
||||
validator_rest_url = '{{ client.validator_rest_url }}'
|
||||
|
||||
# Special mode of the system such that all messages are sent as soon as they are received
|
||||
# and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
# 'Debug' values will have no effect.
|
||||
vpn_mode = {{ client.vpn_mode }}
|
||||
# Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
validator_api_urls = [
|
||||
{{#each client.validator_api_urls }}
|
||||
'{{this}}',
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
# Path to file containing private identity key.
|
||||
private_identity_key_file = '{{ client.private_identity_key_file }}'
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::{Config, SocketType};
|
||||
use crate::websocket;
|
||||
@@ -42,8 +31,7 @@ use gateway_client::{
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
@@ -106,21 +94,20 @@ impl NymClient {
|
||||
info!("Starting loop cover traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor which HAS TO be called within context of a tokio runtime
|
||||
self.runtime
|
||||
.enter(|| {
|
||||
LoopCoverTrafficStream::new(
|
||||
self.key_manager.ack_key(),
|
||||
self.config.get_base().get_average_ack_delay(),
|
||||
self.config.get_base().get_average_packet_delay(),
|
||||
self.config
|
||||
.get_base()
|
||||
.get_loop_cover_traffic_average_delay(),
|
||||
mix_tx,
|
||||
self.as_mix_recipient(),
|
||||
topology_accessor,
|
||||
)
|
||||
})
|
||||
.start(self.runtime.handle());
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
LoopCoverTrafficStream::new(
|
||||
self.key_manager.ack_key(),
|
||||
self.config.get_base().get_average_ack_delay(),
|
||||
self.config.get_base().get_average_packet_delay(),
|
||||
self.config
|
||||
.get_base()
|
||||
.get_loop_cover_traffic_average_delay(),
|
||||
mix_tx,
|
||||
self.as_mix_recipient(),
|
||||
topology_accessor,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
}
|
||||
|
||||
fn start_real_traffic_controller(
|
||||
@@ -131,12 +118,6 @@ impl NymClient {
|
||||
input_receiver: InputMessageReceiver,
|
||||
mix_sender: BatchMixMessageSender,
|
||||
) {
|
||||
let packet_mode = if self.config.get_base().get_vpn_mode() {
|
||||
PacketMode::VPN
|
||||
} else {
|
||||
PacketMode::Mix
|
||||
};
|
||||
|
||||
let controller_config = real_messages_control::Config::new(
|
||||
self.key_manager.ack_key(),
|
||||
self.config.get_base().get_ack_wait_multiplier(),
|
||||
@@ -145,26 +126,23 @@ impl NymClient {
|
||||
self.config.get_base().get_message_sending_average_delay(),
|
||||
self.config.get_base().get_average_packet_delay(),
|
||||
self.as_mix_recipient(),
|
||||
packet_mode,
|
||||
self.config.get_base().get_vpn_key_reuse_limit(),
|
||||
);
|
||||
|
||||
info!("Starting real traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor [of OutQueueControl] which HAS TO be called within context of a tokio runtime
|
||||
// When refactoring this restriction should definitely be removed.
|
||||
let real_messages_controller = self.runtime.enter(|| {
|
||||
RealMessagesController::new(
|
||||
controller_config,
|
||||
ack_receiver,
|
||||
input_receiver,
|
||||
mix_sender,
|
||||
topology_accessor,
|
||||
reply_key_storage,
|
||||
)
|
||||
});
|
||||
real_messages_controller
|
||||
.start(self.runtime.handle(), self.config.get_base().get_vpn_mode());
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
RealMessagesController::new(
|
||||
controller_config,
|
||||
ack_receiver,
|
||||
input_receiver,
|
||||
mix_sender,
|
||||
topology_accessor,
|
||||
reply_key_storage,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
}
|
||||
|
||||
// buffer controlling all messages fetched from provider
|
||||
@@ -202,41 +180,38 @@ impl NymClient {
|
||||
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
||||
.expect("provided gateway id is invalid!");
|
||||
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
);
|
||||
|
||||
self.runtime.block_on(async {
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
);
|
||||
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
.expect("could not authenticate and start up the gateway connection")
|
||||
});
|
||||
.expect("could not authenticate and start up the gateway connection");
|
||||
|
||||
gateway_client
|
||||
gateway_client
|
||||
})
|
||||
}
|
||||
|
||||
// future responsible for periodically polling directory server and updating
|
||||
// the current global view of topology
|
||||
fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||
self.config.get_base().get_validator_rest_endpoint(),
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
self.config.get_base().get_topology_refresh_rate(),
|
||||
);
|
||||
let mut topology_refresher =
|
||||
TopologyRefresher::new_directory_client(topology_refresher_config, topology_accessor);
|
||||
TopologyRefresher::new(topology_refresher_config, topology_accessor);
|
||||
// before returning, block entire runtime to refresh the current network view so that any
|
||||
// components depending on topology would see a non-empty view
|
||||
info!(
|
||||
"Obtaining initial network topology from {}",
|
||||
self.config.get_base().get_validator_rest_endpoint()
|
||||
);
|
||||
info!("Obtaining initial network topology");
|
||||
self.runtime.block_on(topology_refresher.refresh());
|
||||
|
||||
// TODO: a slightly more graceful termination here
|
||||
@@ -297,7 +272,7 @@ impl NymClient {
|
||||
/// EXPERIMENTAL DIRECT RUST API
|
||||
/// It's untested and there are absolutely no guarantees about it (but seems to have worked
|
||||
/// well enough in local tests)
|
||||
pub fn send_reply(&mut self, reply_surb: ReplySURB, message: Vec<u8>) {
|
||||
pub fn send_reply(&mut self, reply_surb: ReplySurb, message: Vec<u8>) {
|
||||
let input_msg = InputMessage::new_reply(reply_surb, message);
|
||||
|
||||
self.input_tx
|
||||
@@ -335,7 +310,7 @@ impl NymClient {
|
||||
}
|
||||
|
||||
println!(
|
||||
"Received SIGINT - the client will terminate now (threads are not YET nicely stopped)"
|
||||
"Received SIGINT - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -389,9 +364,7 @@ impl NymClient {
|
||||
sphinx_message_sender.clone(),
|
||||
);
|
||||
|
||||
if !self.config.get_base().get_vpn_mode() {
|
||||
self.start_cover_traffic_stream(shared_topology_accessor, sphinx_message_sender);
|
||||
}
|
||||
self.start_cover_traffic_stream(shared_topology_accessor, sphinx_message_sender);
|
||||
|
||||
match self.config.get_socket_type() {
|
||||
SocketType::WebSocket => {
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::Config;
|
||||
use crate::commands::override_config;
|
||||
@@ -18,14 +7,19 @@ use clap::{App, Arg, ArgMatches};
|
||||
use client_core::client::key_manager::KeyManager;
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use gateway_client::GatewayClient;
|
||||
use gateway_requests::registration::handshake::SharedKeys;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use topology::{gateway, NymTopology};
|
||||
use topology::{filter::VersionFilterable, gateway};
|
||||
use url::Url;
|
||||
|
||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
App::new("init")
|
||||
@@ -41,10 +35,10 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Id of the gateway we are going to connect to.")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(Arg::with_name("validator")
|
||||
.long("validator")
|
||||
.help("Address of the validator server the client is getting topology from")
|
||||
.takes_value(true),
|
||||
.arg(Arg::with_name("validators")
|
||||
.long("validators")
|
||||
.help("Comma separated list of rest endpoints of the validators")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(Arg::with_name("disable-socket")
|
||||
.long("disable-socket")
|
||||
@@ -56,17 +50,6 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Port for the socket (if applicable) to listen on in all subsequent runs")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(Arg::with_name("vpn-mode")
|
||||
.long("vpn-mode")
|
||||
.help("Set the vpn mode of the client")
|
||||
.long_help(
|
||||
r#"
|
||||
Special mode of the system such that all messages are sent as soon as they are received
|
||||
and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
'Debug' values will have no effect.
|
||||
"#
|
||||
)
|
||||
)
|
||||
.arg(Arg::with_name("fastmode")
|
||||
.long("fastmode")
|
||||
.hidden(true) // this will prevent this flag from being displayed in `--help`
|
||||
@@ -77,10 +60,10 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
async fn register_with_gateway(
|
||||
gateway: &gateway::Node,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
) -> SharedKeys {
|
||||
) -> Arc<SharedKeys> {
|
||||
let timeout = Duration::from_millis(1500);
|
||||
let mut gateway_client = GatewayClient::new_init(
|
||||
gateway.client_listener.clone(),
|
||||
gateway.clients_address(),
|
||||
gateway.identity_key,
|
||||
our_identity.clone(),
|
||||
timeout,
|
||||
@@ -90,44 +73,87 @@ async fn register_with_gateway(
|
||||
.await
|
||||
.expect("failed to establish connection with the gateway!");
|
||||
gateway_client
|
||||
.register()
|
||||
.perform_initial_authentication()
|
||||
.await
|
||||
.expect("failed to register with the gateway!")
|
||||
}
|
||||
|
||||
async fn gateway_details(validator_server: &str, chosen_gateway_id: Option<&str>) -> gateway::Node {
|
||||
let validator_client_config = validator_client::Config::new(validator_server.to_string());
|
||||
let validator_client = validator_client::Client::new(validator_client_config);
|
||||
let topology = validator_client.get_active_topology().await.unwrap();
|
||||
let nym_topology: NymTopology = topology.into();
|
||||
let version_filtered_topology = nym_topology.filter_system_version(env!("CARGO_PKG_VERSION"));
|
||||
async fn gateway_details(
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<&str>,
|
||||
) -> gateway::Node {
|
||||
let validator_api = validator_servers
|
||||
.choose(&mut thread_rng())
|
||||
.expect("The list of validator apis is empty");
|
||||
let validator_client = validator_client::ApiClient::new(validator_api.clone());
|
||||
|
||||
let gateways = validator_client.get_cached_gateways().await.unwrap();
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
.collect::<Vec<gateway::Node>>();
|
||||
|
||||
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
|
||||
|
||||
// if we have chosen particular gateway - use it, otherwise choose a random one.
|
||||
// (remember that in active topology all gateways have at least 100 reputation so should
|
||||
// be working correctly)
|
||||
|
||||
if let Some(gateway_id) = chosen_gateway_id {
|
||||
version_filtered_topology
|
||||
.gateways()
|
||||
filtered_gateways
|
||||
.iter()
|
||||
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
|
||||
.expect(&*format!("no gateway with id {} exists!", gateway_id))
|
||||
.clone()
|
||||
} else {
|
||||
version_filtered_topology
|
||||
.gateways()
|
||||
filtered_gateways
|
||||
.choose(&mut rand::thread_rng())
|
||||
.expect("there are no gateways on the network!")
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn show_address(config: &Config) {
|
||||
fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair {
|
||||
let identity_keypair: identity::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
pathfinder.public_identity_key().to_owned(),
|
||||
))
|
||||
.expect("Failed to read stored identity key files");
|
||||
identity_keypair
|
||||
}
|
||||
|
||||
fn load_sphinx_keys(pathfinder: &ClientKeyPathfinder) -> encryption::KeyPair {
|
||||
let sphinx_keypair: encryption::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_encryption_key().to_owned(),
|
||||
pathfinder.public_encryption_key().to_owned(),
|
||||
))
|
||||
.expect("Failed to read stored sphinx key files");
|
||||
sphinx_keypair
|
||||
}
|
||||
|
||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||
let identity_keypair = load_identity_keys(&pathfinder);
|
||||
let sphinx_keypair = load_sphinx_keys(&pathfinder);
|
||||
|
||||
let client_recipient = Recipient::new(
|
||||
*identity_keypair.public_key(),
|
||||
*sphinx_keypair.public_key(),
|
||||
// TODO: below only works under assumption that gateway address == gateway id
|
||||
// (which currently is true)
|
||||
NodeIdentity::from_base58_string(config.get_base().get_gateway_id()).unwrap(),
|
||||
);
|
||||
|
||||
println!("\nThe address of this client is: {}", client_recipient);
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
println!("Initialising client...");
|
||||
|
||||
let id = matches.value_of("id").unwrap(); // required for now
|
||||
|
||||
let already_init = if Config::default_config_file_path(id).exists() {
|
||||
let already_init = if Config::default_config_file_path(Some(id)).exists() {
|
||||
println!("Client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
|
||||
true
|
||||
} else {
|
||||
@@ -155,7 +181,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
let registration_fut = async {
|
||||
let gate_details = gateway_details(
|
||||
&config.get_base().get_validator_rest_endpoint(),
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
@@ -164,11 +190,11 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.with_gateway_id(gate_details.identity_key.to_base58_string());
|
||||
let shared_keys =
|
||||
register_with_gateway(&gate_details, key_manager.identity_keypair()).await;
|
||||
(shared_keys, gate_details.client_listener)
|
||||
(shared_keys, gate_details.clients_address())
|
||||
};
|
||||
|
||||
// TODO: is there perhaps a way to make it work without having to spawn entire runtime?
|
||||
let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let (shared_keys, gateway_listener) = rt.block_on(registration_fut);
|
||||
config
|
||||
.get_base_mut()
|
||||
@@ -188,5 +214,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.expect("Failed to save the config file");
|
||||
println!("Saved configuration file to {:?}", config_save_location);
|
||||
println!("Using gateway: {}", config.get_base().get_gateway_id(),);
|
||||
println!("Client configuration completed.\n\n\n")
|
||||
println!("Client configuration completed.\n\n\n");
|
||||
|
||||
show_address(&config);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::{Config, SocketType};
|
||||
use clap::ArgMatches;
|
||||
use url::Url;
|
||||
|
||||
pub(crate) mod init;
|
||||
pub(crate) mod run;
|
||||
pub(crate) mod upgrade;
|
||||
|
||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
|
||||
if let Some(validator) = matches.value_of("validator") {
|
||||
config.get_base_mut().set_custom_validator(validator);
|
||||
if let Some(raw_validators) = matches.value_of("validators") {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(parse_validators(raw_validators));
|
||||
}
|
||||
|
||||
if let Some(gateway_id) = matches.value_of("gateway") {
|
||||
@@ -32,10 +35,6 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi
|
||||
config = config.with_socket(SocketType::None);
|
||||
}
|
||||
|
||||
if matches.is_present("vpn-mode") {
|
||||
config.get_base_mut().set_vpn_mode(true);
|
||||
}
|
||||
|
||||
if let Some(port) = matches.value_of("port").map(|port| port.parse::<u16>()) {
|
||||
if let Err(err) = port {
|
||||
// if port was overridden, it must be parsable
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::Config;
|
||||
use crate::client::NymClient;
|
||||
@@ -30,10 +19,10 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.required(true)
|
||||
)
|
||||
// the rest of arguments are optional, they are used to override settings in config file
|
||||
.arg(Arg::with_name("validator")
|
||||
.long("validator")
|
||||
.help("Address of the validator server the client is getting topology from")
|
||||
.takes_value(true),
|
||||
.arg(Arg::with_name("validators")
|
||||
.long("validators")
|
||||
.help("Comma separated list rest rest endpoints of the validators")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(Arg::with_name("gateway")
|
||||
.long("gateway")
|
||||
@@ -44,17 +33,6 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.long("disable-socket")
|
||||
.help("Whether to not start the websocket")
|
||||
)
|
||||
.arg(Arg::with_name("vpn-mode")
|
||||
.long("vpn-mode")
|
||||
.help("Set the vpn mode of the client")
|
||||
.long_help(
|
||||
r#"
|
||||
Special mode of the system such that all messages are sent as soon as they are received
|
||||
and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
'Debug' values will have no effect.
|
||||
"#
|
||||
)
|
||||
)
|
||||
.arg(Arg::with_name("port")
|
||||
.short("p")
|
||||
.long("port")
|
||||
@@ -85,7 +63,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let id = matches.value_of("id").unwrap();
|
||||
|
||||
let mut config = match Config::load_from_file(id) {
|
||||
let mut config = match Config::load_from_file(Some(id)) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})", id, err);
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::{Config, MISSING_VALUE};
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use client_core::config::DEFAULT_VALIDATOR_REST_ENDPOINT;
|
||||
use config::defaults::default_api_endpoints;
|
||||
use config::NymConfig;
|
||||
use std::fmt::Display;
|
||||
use std::process;
|
||||
use version_checker::{parse_version, Version};
|
||||
use version_checker::Version;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> ! {
|
||||
print_failed_upgrade(from_version, to_version);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
|
||||
println!(
|
||||
"\n==================\nTrying to upgrade mixnode from {} to {} ...",
|
||||
"\n==================\nTrying to upgrade client from {} to {} ...",
|
||||
from, to
|
||||
);
|
||||
}
|
||||
@@ -41,147 +36,136 @@ fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
|
||||
);
|
||||
}
|
||||
|
||||
fn pre_090_upgrade(from: &str, mut config: Config) -> Config {
|
||||
// this is not extracted to separate function as you only have to manually pass version
|
||||
// if upgrading from pre090 version
|
||||
let from = match from.strip_prefix("v") {
|
||||
Some(stripped) => stripped,
|
||||
None => from,
|
||||
};
|
||||
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
|
||||
eprintln!(
|
||||
"Cannot perform upgrade from {} to {}. Your version is too old to perform the upgrade.!",
|
||||
config_version, package_version
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
let from = match from.strip_prefix("V") {
|
||||
Some(stripped) => stripped,
|
||||
None => from,
|
||||
};
|
||||
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
|
||||
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue if you expected it to work!", config_version, current_version);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
let from_version = parse_version(from).expect("invalid version provided!");
|
||||
if from_version.major == 0 && from_version.minor < 8 {
|
||||
// technically this could be implemented, but is there any point in that?
|
||||
eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead");
|
||||
pub fn command_args<'a, 'b>() -> App<'a, 'b> {
|
||||
App::new("upgrade").about("Try to upgrade the client").arg(
|
||||
Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-client we want to upgrade")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_config_version(config: &Config) -> Version {
|
||||
let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse client version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
if version.is_prerelease() || !version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade from a non-released version {}. This is not supported!",
|
||||
version
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 {
|
||||
eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version");
|
||||
version
|
||||
}
|
||||
|
||||
fn parse_package_version() -> Version {
|
||||
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
|
||||
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
|
||||
// however, we are not using them ourselves at the moment and hence it should be fine.
|
||||
// if we change our mind, we could easily tweak this code
|
||||
if version.is_prerelease() || !version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade to a non-released version {}. This is not supported!",
|
||||
version
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
// note: current is guaranteed to not have any `build` information suffix (nor pre-release
|
||||
// information), as this was asserted at the beginning of this command)
|
||||
//
|
||||
// upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate
|
||||
// step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0)
|
||||
// this way we don't need to have all the crazy paths on how to upgrade from any version to any
|
||||
// other version. We just upgrade one minor version at a time.
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
let to_version = if current.major == 0 && current.minor == 9 {
|
||||
current
|
||||
version
|
||||
}
|
||||
|
||||
fn minor_0_12_upgrade(
|
||||
mut config: Config,
|
||||
_matches: &ArgMatches,
|
||||
config_version: &Version,
|
||||
package_version: &Version,
|
||||
) -> Config {
|
||||
let to_version = if package_version.major == 0 && package_version.minor == 12 {
|
||||
package_version.clone()
|
||||
} else {
|
||||
Version::new(0, 9, 0)
|
||||
Version::new(0, 12, 0)
|
||||
};
|
||||
|
||||
if config.get_base().get_validator_rest_endpoint() != MISSING_VALUE {
|
||||
eprintln!("existing config seems to have specified new validator rest endpoint which was only introduced in 0.9.0! Can't perform upgrade.");
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1);
|
||||
}
|
||||
print_start_upgrade(&config_version, &to_version);
|
||||
|
||||
print_start_upgrade(&from_version, &to_version);
|
||||
println!(
|
||||
"Setting validator API endpoints to {:?}",
|
||||
default_api_endpoints()
|
||||
);
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(default_api_endpoints());
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
println!(
|
||||
"Setting validator REST endpoint to to {}",
|
||||
DEFAULT_VALIDATOR_REST_ENDPOINT
|
||||
);
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator(DEFAULT_VALIDATOR_REST_ENDPOINT);
|
||||
|
||||
config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {:?}", err);
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
print_failed_upgrade(&config_version, &to_version);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(from_version, to_version);
|
||||
print_successful_upgrade(config_version, to_version);
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
pub fn command_args<'a, 'b>() -> App<'a, 'b> {
|
||||
App::new("upgrade").about("Try to upgrade the mixnode")
|
||||
.arg(
|
||||
Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-client we want to upgrade")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
// the rest of arguments depend on the upgrade path
|
||||
.arg(Arg::with_name("current version")
|
||||
.long("current-version")
|
||||
.help("REQUIRED FOR PRE-0.9.0 UPGRADES. Specifies current version of the configuration file to help to determine a valid upgrade path. Valid formats include '0.8.1', 'v0.8.1' or 'V0.8.1'")
|
||||
.takes_value(true)
|
||||
)
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version) {
|
||||
loop {
|
||||
let config_version = parse_config_version(&config);
|
||||
|
||||
if config_version == package_version {
|
||||
println!("You're using the most recent version!");
|
||||
return;
|
||||
}
|
||||
|
||||
config = match config_version.major {
|
||||
0 => match config_version.minor {
|
||||
9 | 10 => outdated_upgrade(&config_version, &package_version),
|
||||
11 => minor_0_12_upgrade(config, matches, &config_version, &package_version),
|
||||
_ => unsupported_upgrade(&config_version, &package_version),
|
||||
},
|
||||
_ => unsupported_upgrade(&config_version, &package_version),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
|
||||
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
|
||||
// however, we are not using them ourselves at the moment and hence it should be fine.
|
||||
// if we change our mind, we could easily tweak this code
|
||||
if current.is_prerelease() || !current.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade to a non-released version {}. This is not supported!",
|
||||
current
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
let package_version = parse_package_version();
|
||||
|
||||
let id = matches.value_of("id").unwrap();
|
||||
|
||||
let mut existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
|
||||
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
|
||||
eprintln!("failed to load existing config file! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
// versions fields were added in 0.9.0
|
||||
if existing_config.get_base().get_version() == MISSING_VALUE {
|
||||
let self_reported_version = matches.value_of("current version").unwrap_or_else(|| {
|
||||
eprintln!(
|
||||
"trying to upgrade from pre v0.9.0 without providing current system version!"
|
||||
);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
// upgrades up to 0.9.0
|
||||
existing_config = pre_090_upgrade(self_reported_version, existing_config);
|
||||
eprintln!("the existing configuration file does not seem to contain version number.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let config_version =
|
||||
Version::parse(existing_config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse node version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
if config_version.is_prerelease() || !config_version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade to from non-released version {}. This is not supported!",
|
||||
current
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
// here be upgrade path to 0.10.0 and beyond based on version number from config
|
||||
if config_version == current {
|
||||
println!("You're using the most recent version!");
|
||||
} else {
|
||||
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue!", config_version, current);
|
||||
process::exit(1)
|
||||
}
|
||||
// here be upgrade path to 0.9.X and beyond based on version number from config
|
||||
do_upgrade(existing_config, matches, package_version)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod client;
|
||||
pub mod websocket;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{App, ArgMatches};
|
||||
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use client_core::client::{
|
||||
inbound_messages::{InputMessage, InputMessageSender},
|
||||
@@ -22,7 +11,7 @@ use futures::channel::mpsc;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_tungstenite::{
|
||||
@@ -100,9 +89,9 @@ impl Handler {
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_reply(&mut self, reply_surb: ReplySURB, message: Vec<u8>) -> Option<ServerResponse> {
|
||||
if message.len() > ReplySURB::max_msg_len(Default::default()) {
|
||||
return Some(ServerResponse::new_error(format!("too long message to put inside a reply SURB. Received: {} bytes and maximum is {} bytes", message.len(), ReplySURB::max_msg_len(Default::default()))));
|
||||
fn handle_reply(&mut self, reply_surb: ReplySurb, message: Vec<u8>) -> Option<ServerResponse> {
|
||||
if message.len() > ReplySurb::max_msg_len(Default::default()) {
|
||||
return Some(ServerResponse::new_error(format!("too long message to put inside a reply SURB. Received: {} bytes and maximum is {} bytes", message.len(), ReplySurb::max_msg_len(Default::default()))));
|
||||
}
|
||||
|
||||
let input_msg = InputMessage::new_reply(reply_surb, message);
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::handler::Handler;
|
||||
use log::*;
|
||||
use std::{
|
||||
net::{Shutdown, SocketAddr},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{net::SocketAddr, process, sync::Arc};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::runtime;
|
||||
use tokio::{sync::Notify, task::JoinHandle};
|
||||
|
||||
@@ -47,9 +34,13 @@ impl Listener {
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self, handler: Handler) {
|
||||
let mut tcp_listener = tokio::net::TcpListener::bind(self.address)
|
||||
.await
|
||||
.expect("Failed to start websocket listener");
|
||||
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
||||
Ok(listener) => listener,
|
||||
Err(err) => {
|
||||
error!("Failed to bind to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address, err);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let notify = Arc::new(Notify::new());
|
||||
|
||||
@@ -61,7 +52,7 @@ impl Listener {
|
||||
}
|
||||
new_conn = tcp_listener.accept() => {
|
||||
match new_conn {
|
||||
Ok((socket, remote_addr)) => {
|
||||
Ok((mut socket, remote_addr)) => {
|
||||
debug!("Received connection from {:?}", remote_addr);
|
||||
if self.state.is_connected() {
|
||||
warn!("tried to duplicate!");
|
||||
@@ -70,7 +61,7 @@ impl Listener {
|
||||
// while we only ever want to accept a single connection, we don't want
|
||||
// to leave clients hanging (and also allow for reconnection if it somehow
|
||||
// was dropped)
|
||||
match socket.shutdown(Shutdown::Both) {
|
||||
match socket.shutdown().await {
|
||||
Ok(_) => trace!(
|
||||
"closed the connection between attempting websocket handshake"
|
||||
),
|
||||
@@ -84,7 +75,7 @@ impl Listener {
|
||||
let fresh_handler = handler.clone();
|
||||
tokio::spawn(async move {
|
||||
fresh_handler.handle_connection(socket).await;
|
||||
notify_clone.notify();
|
||||
notify_clone.notify_one();
|
||||
});
|
||||
self.state = State::Connected;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub(crate) mod handler;
|
||||
pub(crate) mod listener;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@@ -55,7 +44,7 @@ pub enum ErrorKind {
|
||||
/// The received request is malformed.
|
||||
MalformedRequest = 0x04,
|
||||
|
||||
// that's an arbitrary division but lets keep 1-127 (hex 0x01 - 0x7F) values request-specific
|
||||
// that's an arbitrary division but let's keep 1-127 (hex 0x01 - 0x7F) values request-specific
|
||||
// and 128-254 (hex 0x80 - 0xFE) for responses
|
||||
/// The received response contained no data.
|
||||
EmptyResponse = 0x80,
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod error;
|
||||
pub mod requests;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// all variable size data is always prefixed with u64 length
|
||||
// tags are u8
|
||||
@@ -18,7 +7,7 @@
|
||||
use crate::error::{self, ErrorKind};
|
||||
use crate::text::ClientRequestText;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::mem::size_of;
|
||||
|
||||
@@ -42,7 +31,7 @@ pub enum ClientRequest {
|
||||
},
|
||||
Reply {
|
||||
message: Vec<u8>,
|
||||
reply_surb: ReplySURB,
|
||||
reply_surb: ReplySurb,
|
||||
},
|
||||
SelfAddress,
|
||||
}
|
||||
@@ -119,7 +108,7 @@ impl ClientRequest {
|
||||
}
|
||||
|
||||
// REPLY_REQUEST_TAG || surb_len || surb || message_len || message
|
||||
fn serialize_reply(message: Vec<u8>, reply_surb: ReplySURB) -> Vec<u8> {
|
||||
fn serialize_reply(message: Vec<u8>, reply_surb: ReplySurb) -> Vec<u8> {
|
||||
let reply_surb_bytes = reply_surb.to_bytes();
|
||||
let surb_len_bytes = (reply_surb_bytes.len() as u64).to_be_bytes();
|
||||
let message_len_bytes = (message.len() as u64).to_be_bytes();
|
||||
@@ -164,7 +153,7 @@ impl ClientRequest {
|
||||
let surb_bound = 1 + size_of::<u64>() + reply_surb_len as usize;
|
||||
|
||||
let reply_surb_bytes = &b[1 + size_of::<u64>()..surb_bound];
|
||||
let reply_surb = match ReplySURB::from_bytes(reply_surb_bytes) {
|
||||
let reply_surb = match ReplySurb::from_bytes(reply_surb_bytes) {
|
||||
Ok(reply_surb) => reply_surb,
|
||||
Err(err) => {
|
||||
return Err(error::Error::new(
|
||||
@@ -206,11 +195,11 @@ impl ClientRequest {
|
||||
}
|
||||
|
||||
// SELF_ADDRESS_REQUEST_TAG
|
||||
fn deserialize_self_address(b: &[u8]) -> Result<Self, error::Error> {
|
||||
fn deserialize_self_address(b: &[u8]) -> Self {
|
||||
// this MUST match because it was called by 'deserialize'
|
||||
debug_assert_eq!(b[0], SELF_ADDRESS_REQUEST_TAG);
|
||||
|
||||
Ok(ClientRequest::SelfAddress)
|
||||
ClientRequest::SelfAddress
|
||||
}
|
||||
|
||||
pub fn serialize(self) -> Vec<u8> {
|
||||
@@ -255,7 +244,7 @@ impl ClientRequest {
|
||||
match request_tag {
|
||||
SEND_REQUEST_TAG => Self::deserialize_send(b),
|
||||
REPLY_REQUEST_TAG => Self::deserialize_reply(b),
|
||||
SELF_ADDRESS_REQUEST_TAG => Self::deserialize_self_address(b),
|
||||
SELF_ADDRESS_REQUEST_TAG => Ok(Self::deserialize_self_address(b)),
|
||||
n => Err(error::Error::new(
|
||||
ErrorKind::UnknownRequest,
|
||||
format!("type {}", n),
|
||||
@@ -333,7 +322,7 @@ mod tests {
|
||||
#[test]
|
||||
fn reply_request_serialization_works() {
|
||||
let reply_surb_string = "CjfVbHbfAjbC3W1BvNHGXmM8KNAnDNYGaHMLqVDxRYeo352csAihstup9bvqXam4dTWgfHak6KYwL9STaxWJ47E8XFZbSEvs7hEsfCkxr6K9WJuSBPK84GDDEvad8ZAuMCoaXsAd5S2Lj9a5eYyzG4SL1jHzhSMni55LyJwumxo1ZTGZNXggxw1RREosvyzNrW9Rsi3owyPqLCwXpiei2tHZty8w8midVvg8vDa7ZEJD842CLv8D4ohynSG7gDpqTrhkRaqYAuz7dzqNbMXLJRM7v823Jn16fA1L7YQxmcaUdUigyRSgTdb4i9ebiLGSyJ1iDe6Acz613PQZh6Ua3bZ2zVKq3dSycpDm9ngarRK4zJrAaUxRkdih8YzW3BY4nL9eqkfKA4N1TWCLaRU7zpSaf8yMEwrAZReU3d5zLV8c5KBfa2w8R5anhQeBojduZEGEad8kkHuKU52Zg93FeWHvH1qgZaEJMHH4nN7gKXz9mvWDhYwyF4vt3Uy2NhCHC3N5pL1gMme27YcoPcTEia1fxKZtnt6rtEozzTrAgCJGswigkFbkafiV5QaJwLKTUxtzhkZ57eEuLPte9UvJHzhhXUQ2CV7R2BUkJjYZy3Zsx6YYvdYWiAFFkWUwNEGA4QpShUHciBfsQVHQ7pN41YcyYUhbywQDFnTVgEmdUZ1XCBi3gyK5U3tDQmFzP1u9m3mWrUA8qB9mRDE7ptNDm5c3c1458L6uXLUth7sdMaa1Was5LCmCdmNDtvNpCDAEt1in6q6mrZFR85aCSU9b1baNGwZoCqPpPvydkVe63gXWoi8ebvdyxARrqACFrSB3ZdY3uJBw8CTMNkKK6MvcefMkSVVsbLd36TQAtYSCqrpiMc5dQuKcEu5QfciwvWYXYx8WFNAgKwP2mv49KCTvfozNDUCbjzDwSx92Zv5zjG8HbFpB13bY9UZGeyTPvv7gGxCzjGjJGbW6FRAheRQaaje5fUgCNM95Tv7wBmAMRHHFgWafeK1sdFH7dtCX9u898HucGTaboSKLsVh8J78gbbkHErwjMh7y9YRkceq5TTYS5da4kHnyNKYWSbxgZrmFg44XGKoeYcqoHB3XTZrdsf7F5fFeNwnihkmADvhAcaxXUmVqq4rQFZH84a1iC3WBWXYcqiZH2L7ujGWV7mMDT4HBEerDYjc8rNY4xGTPfivCrBCJW1i14aqW8xRdsdgTM88eTksvC3WPJLJ7iMzfKXeL7fMW1Ek6QGyQtLBW98vEESpdcDg6DeZ5rMz6VqjTGGqcCaFGfHoqtfxMDaBAEsyQ8h7XDX6dg1wq9wH6j4Tw7Tj1MEv1b8uj5NJkozZdzVdYA2QyE2Dp8vuurQG6uVdTDNww2d88RBQ8sVgjxN8gR45y4woJLhFAaNTAtrY6wDTxyXST13ni6oyqdYxjFVk9Am4v3DzH7Y2K8iRVSHfTk4FRbPULyaeK6wt2anvMJH1XdvVRgc14h67MnBxMgMD1UFk8AErN7CDj26fppe3c5G6KozJe4cSqQUGbBjVzBnrHCruqrfZBn5hNZHTV37bQiomqhRQXohxhuKEnNrGbAe1xNvJr9X";
|
||||
let reply_surb = ReplySURB::from_base58_string(reply_surb_string).unwrap();
|
||||
let reply_surb = ReplySurb::from_base58_string(reply_surb_string).unwrap();
|
||||
let reply_request = ClientRequest::Reply {
|
||||
message: b"foomp".to_vec(),
|
||||
reply_surb,
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// all variable size data is always prefixed with u64 length
|
||||
// tags are u8
|
||||
|
||||
#![allow(unknown_lints)] // due to using `clippy::branches_sharing_code` which does not exist on `stable` just yet
|
||||
|
||||
use crate::error::{self, ErrorKind};
|
||||
use crate::text::ServerResponseText;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use std::convert::TryInto;
|
||||
use std::mem::size_of;
|
||||
@@ -96,6 +87,8 @@ impl ServerResponse {
|
||||
}
|
||||
};
|
||||
|
||||
// this is a false positive as even though the code is the same, it refers to different things
|
||||
#[allow(clippy::branches_sharing_code)]
|
||||
if with_reply_surb {
|
||||
let reply_surb_len =
|
||||
u64::from_be_bytes(b[2..2 + size_of::<u64>()].as_ref().try_into().unwrap());
|
||||
@@ -111,7 +104,7 @@ impl ServerResponse {
|
||||
let surb_bound = 2 + size_of::<u64>() + reply_surb_len as usize;
|
||||
|
||||
let reply_surb_bytes = &b[2 + size_of::<u64>()..surb_bound];
|
||||
let reply_surb = match ReplySURB::from_bytes(reply_surb_bytes) {
|
||||
let reply_surb = match ReplySurb::from_bytes(reply_surb_bytes) {
|
||||
Ok(reply_surb) => reply_surb,
|
||||
Err(err) => {
|
||||
return Err(error::Error::new(
|
||||
@@ -339,7 +332,7 @@ mod tests {
|
||||
|
||||
let received_with_surb = ServerResponse::Received(ReconstructedMessage {
|
||||
message: b"foomp".to_vec(),
|
||||
reply_surb: Some(ReplySURB::from_base58_string(reply_surb_string).unwrap()),
|
||||
reply_surb: Some(ReplySurb::from_base58_string(reply_surb_string).unwrap()),
|
||||
});
|
||||
let bytes = received_with_surb.serialize();
|
||||
let recovered = ServerResponse::deserialize(&bytes).unwrap();
|
||||
|
||||
@@ -1,22 +1,11 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::ErrorKind;
|
||||
use crate::requests::ClientRequest;
|
||||
use crate::responses::ServerResponse;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
@@ -75,7 +64,7 @@ impl TryInto<ClientRequest> for ClientRequestText {
|
||||
reply_surb,
|
||||
} => {
|
||||
let message_bytes = message.into_bytes();
|
||||
let reply_surb = ReplySURB::from_base58_string(reply_surb).map_err(|err| {
|
||||
let reply_surb = ReplySurb::from_base58_string(reply_surb).map_err(|err| {
|
||||
Self::Error::new(ErrorKind::MalformedRequest, err.to_string())
|
||||
})?;
|
||||
|
||||
@@ -115,15 +104,15 @@ impl TryFrom<String> for ServerResponseText {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for ServerResponseText {
|
||||
fn into(self) -> String {
|
||||
impl From<ServerResponseText> for String {
|
||||
fn from(res: ServerResponseText) -> Self {
|
||||
// per serde_json docs:
|
||||
/*
|
||||
/// Serialization can fail if `T`'s implementation of `Serialize` decides to
|
||||
/// fail, or if `T` contains a map with non-string keys.
|
||||
*/
|
||||
// this is not the case here.
|
||||
serde_json::to_string(&self).unwrap()
|
||||
serde_json::to_string(&res).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "0.9.0"
|
||||
version = "0.11.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -14,12 +14,13 @@ dirs = "3.0" # for determining default store directories in config
|
||||
dotenv = "0.15.0"
|
||||
futures = "0.3"
|
||||
log = "0.4"
|
||||
pin-project = "0.4"
|
||||
pretty_env_logger = "0.3"
|
||||
pin-project = "1.0"
|
||||
pretty_env_logger = "0.4"
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
serde = { version = "1.0", features = ["derive"] } # for config serialization/deserialization
|
||||
snafu = "0.4.1"
|
||||
tokio = { version = "0.2", features = ["rt-threaded"] }
|
||||
snafu = "0.6"
|
||||
tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal"] }
|
||||
url = "2.2"
|
||||
|
||||
# internal
|
||||
client-core = { path = "../client-core" }
|
||||
@@ -31,6 +32,7 @@ nymsphinx = { path = "../../common/nymsphinx" }
|
||||
ordered-buffer = {path = "../../common/socks5/ordered-buffer"}
|
||||
socks5-requests = { path = "../../common/socks5/requests" }
|
||||
topology = { path = "../../common/topology" }
|
||||
pemstore = { path = "../../common/pemstore" }
|
||||
proxy-helpers = { path = "../../common/socks5/proxy-helpers" }
|
||||
validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
version-checker = { path = "../../common/version-checker" }
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::template::config_template;
|
||||
use client_core::config::Config as BaseConfig;
|
||||
pub use client_core::config::MISSING_VALUE;
|
||||
use config::defaults::DEFAULT_SOCKS5_LISTENING_PORT;
|
||||
use config::NymConfig;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -22,8 +12,6 @@ use std::path::PathBuf;
|
||||
|
||||
mod template;
|
||||
|
||||
const DEFAULT_LISTENING_PORT: u16 = 1080;
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
@@ -114,7 +102,7 @@ pub struct Socks5 {
|
||||
impl Socks5 {
|
||||
pub fn new<S: Into<String>>(provider_mix_address: S) -> Self {
|
||||
Socks5 {
|
||||
listening_port: DEFAULT_LISTENING_PORT,
|
||||
listening_port: DEFAULT_SOCKS5_LISTENING_PORT,
|
||||
provider_mix_address: provider_mix_address.into(),
|
||||
}
|
||||
}
|
||||
@@ -123,7 +111,7 @@ impl Socks5 {
|
||||
impl Default for Socks5 {
|
||||
fn default() -> Self {
|
||||
Socks5 {
|
||||
listening_port: DEFAULT_LISTENING_PORT,
|
||||
listening_port: DEFAULT_SOCKS5_LISTENING_PORT,
|
||||
provider_mix_address: "".into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,11 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub(crate) fn config_template() -> &'static str {
|
||||
// While using normal toml marshalling would have been way simpler with less overhead,
|
||||
// I think it's useful to have comments attached to the saved config file to explain behaviour of
|
||||
// particular fields.
|
||||
// Note: any changes to the template must be reflected in the appropriate structs in mod.rs.
|
||||
// Note: any changes to the template must be reflected in the appropriate structs in verloc.
|
||||
r#"
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
@@ -30,13 +19,12 @@ version = '{{ client.version }}'
|
||||
# Human readable ID of this particular client.
|
||||
id = '{{ client.id }}'
|
||||
|
||||
# URL to the validator server for obtaining network topology.
|
||||
validator_rest_url = '{{ client.validator_rest_url }}'
|
||||
|
||||
# Special mode of the system such that all messages are sent as soon as they are received
|
||||
# and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
# 'Debug' values will have no effect.
|
||||
vpn_mode = {{ client.vpn_mode }}
|
||||
# Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
validator_api_urls = [
|
||||
{{#each client.validator_api_urls }}
|
||||
'{{this}}',
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
# Path to file containing private identity key.
|
||||
private_identity_key_file = '{{ client.private_identity_key_file }}'
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::Config;
|
||||
use crate::socks::{
|
||||
@@ -43,7 +32,6 @@ use gateway_client::{
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
pub(crate) mod config;
|
||||
@@ -94,21 +82,20 @@ impl NymClient {
|
||||
info!("Starting loop cover traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor which HAS TO be called within context of a tokio runtime
|
||||
self.runtime
|
||||
.enter(|| {
|
||||
LoopCoverTrafficStream::new(
|
||||
self.key_manager.ack_key(),
|
||||
self.config.get_base().get_average_ack_delay(),
|
||||
self.config.get_base().get_average_packet_delay(),
|
||||
self.config
|
||||
.get_base()
|
||||
.get_loop_cover_traffic_average_delay(),
|
||||
mix_tx,
|
||||
self.as_mix_recipient(),
|
||||
topology_accessor,
|
||||
)
|
||||
})
|
||||
.start(self.runtime.handle());
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
LoopCoverTrafficStream::new(
|
||||
self.key_manager.ack_key(),
|
||||
self.config.get_base().get_average_ack_delay(),
|
||||
self.config.get_base().get_average_packet_delay(),
|
||||
self.config
|
||||
.get_base()
|
||||
.get_loop_cover_traffic_average_delay(),
|
||||
mix_tx,
|
||||
self.as_mix_recipient(),
|
||||
topology_accessor,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
}
|
||||
|
||||
fn start_real_traffic_controller(
|
||||
@@ -119,12 +106,6 @@ impl NymClient {
|
||||
input_receiver: InputMessageReceiver,
|
||||
mix_sender: BatchMixMessageSender,
|
||||
) {
|
||||
let packet_mode = if self.config.get_base().get_vpn_mode() {
|
||||
PacketMode::VPN
|
||||
} else {
|
||||
PacketMode::Mix
|
||||
};
|
||||
|
||||
let controller_config = client_core::client::real_messages_control::Config::new(
|
||||
self.key_manager.ack_key(),
|
||||
self.config.get_base().get_ack_wait_multiplier(),
|
||||
@@ -133,26 +114,23 @@ impl NymClient {
|
||||
self.config.get_base().get_message_sending_average_delay(),
|
||||
self.config.get_base().get_average_packet_delay(),
|
||||
self.as_mix_recipient(),
|
||||
packet_mode,
|
||||
self.config.get_base().get_vpn_key_reuse_limit(),
|
||||
);
|
||||
|
||||
info!("Starting real traffic stream...");
|
||||
// we need to explicitly enter runtime due to "next_delay: time::delay_for(Default::default())"
|
||||
// set in the constructor [of OutQueueControl] which HAS TO be called within context of a tokio runtime
|
||||
// When refactoring this restriction should definitely be removed.
|
||||
let real_messages_controller = self.runtime.enter(|| {
|
||||
RealMessagesController::new(
|
||||
controller_config,
|
||||
ack_receiver,
|
||||
input_receiver,
|
||||
mix_sender,
|
||||
topology_accessor,
|
||||
reply_key_storage,
|
||||
)
|
||||
});
|
||||
real_messages_controller
|
||||
.start(self.runtime.handle(), self.config.get_base().get_vpn_mode());
|
||||
let _guard = self.runtime.enter();
|
||||
|
||||
RealMessagesController::new(
|
||||
controller_config,
|
||||
ack_receiver,
|
||||
input_receiver,
|
||||
mix_sender,
|
||||
topology_accessor,
|
||||
reply_key_storage,
|
||||
)
|
||||
.start(self.runtime.handle());
|
||||
}
|
||||
|
||||
// buffer controlling all messages fetched from provider
|
||||
@@ -190,41 +168,38 @@ impl NymClient {
|
||||
let gateway_identity = identity::PublicKey::from_base58_string(gateway_id)
|
||||
.expect("provided gateway id is invalid!");
|
||||
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
);
|
||||
|
||||
self.runtime.block_on(async {
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
gateway_address,
|
||||
self.key_manager.identity_keypair(),
|
||||
gateway_identity,
|
||||
Some(self.key_manager.gateway_shared_key()),
|
||||
mixnet_message_sender,
|
||||
ack_sender,
|
||||
self.config.get_base().get_gateway_response_timeout(),
|
||||
);
|
||||
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
.expect("could not authenticate and start up the gateway connection")
|
||||
});
|
||||
.expect("could not authenticate and start up the gateway connection");
|
||||
|
||||
gateway_client
|
||||
gateway_client
|
||||
})
|
||||
}
|
||||
|
||||
// future responsible for periodically polling directory server and updating
|
||||
// the current global view of topology
|
||||
fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) {
|
||||
let topology_refresher_config = TopologyRefresherConfig::new(
|
||||
self.config.get_base().get_validator_rest_endpoint(),
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
self.config.get_base().get_topology_refresh_rate(),
|
||||
);
|
||||
let mut topology_refresher =
|
||||
TopologyRefresher::new_directory_client(topology_refresher_config, topology_accessor);
|
||||
TopologyRefresher::new(topology_refresher_config, topology_accessor);
|
||||
// before returning, block entire runtime to refresh the current network view so that any
|
||||
// components depending on topology would see a non-empty view
|
||||
info!(
|
||||
"Obtaining initial network topology from {}",
|
||||
self.config.get_base().get_validator_rest_endpoint()
|
||||
);
|
||||
info!("Obtaining initial network topology");
|
||||
self.runtime.block_on(topology_refresher.refresh());
|
||||
|
||||
// TODO: a slightly more graceful termination here
|
||||
@@ -261,8 +236,7 @@ impl NymClient {
|
||||
msg_input: InputMessageSender,
|
||||
) {
|
||||
info!("Starting socks5 listener...");
|
||||
let mut auth_methods: Vec<u8> = Vec::new();
|
||||
auth_methods.push(AuthenticationMethods::NoAuth as u8);
|
||||
let auth_methods = vec![AuthenticationMethods::NoAuth as u8];
|
||||
let allowed_users: Vec<User> = Vec::new();
|
||||
|
||||
let authenticator = Authenticator::new(auth_methods, allowed_users);
|
||||
@@ -287,7 +261,7 @@ impl NymClient {
|
||||
}
|
||||
|
||||
println!(
|
||||
"Received SIGINT - the client will terminate now (threads are not YET nicely stopped)"
|
||||
"Received SIGINT - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -340,9 +314,8 @@ impl NymClient {
|
||||
input_receiver,
|
||||
sphinx_message_sender.clone(),
|
||||
);
|
||||
if !self.config.get_base().get_vpn_mode() {
|
||||
self.start_cover_traffic_stream(shared_topology_accessor, sphinx_message_sender);
|
||||
}
|
||||
|
||||
self.start_cover_traffic_stream(shared_topology_accessor, sphinx_message_sender);
|
||||
self.start_socks5_listener(received_buffer_request_sender, input_sender);
|
||||
|
||||
info!("Client startup finished!");
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::Config;
|
||||
use crate::commands::override_config;
|
||||
@@ -18,13 +7,17 @@ use clap::{App, Arg, ArgMatches};
|
||||
use client_core::client::key_manager::KeyManager;
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use gateway_client::GatewayClient;
|
||||
use gateway_requests::registration::handshake::SharedKeys;
|
||||
use rand::{prelude::SliceRandom, rngs::OsRng};
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use rand::{prelude::SliceRandom, rngs::OsRng, thread_rng};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use topology::{gateway, NymTopology};
|
||||
use topology::{filter::VersionFilterable, gateway};
|
||||
use url::Url;
|
||||
|
||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
App::new("init")
|
||||
@@ -46,10 +39,10 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Id of the gateway we are going to connect to.")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(Arg::with_name("validator")
|
||||
.long("validator")
|
||||
.help("Address of the validator server the client is getting topology from")
|
||||
.takes_value(true),
|
||||
.arg(Arg::with_name("validators")
|
||||
.long("validators")
|
||||
.help("Comma separated list of rest endpoints of the validators")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(Arg::with_name("port")
|
||||
.short("p")
|
||||
@@ -57,17 +50,6 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Port for the socket to listen on in all subsequent runs")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(Arg::with_name("vpn-mode")
|
||||
.long("vpn-mode")
|
||||
.help("Set the vpn mode of the client")
|
||||
.long_help(
|
||||
r#"
|
||||
Special mode of the system such that all messages are sent as soon as they are received
|
||||
and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
'Debug' values will have no effect.
|
||||
"#
|
||||
)
|
||||
)
|
||||
.arg(Arg::with_name("fastmode")
|
||||
.long("fastmode")
|
||||
.hidden(true) // this will prevent this flag from being displayed in `--help`
|
||||
@@ -78,10 +60,10 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
async fn register_with_gateway(
|
||||
gateway: &gateway::Node,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
) -> SharedKeys {
|
||||
) -> Arc<SharedKeys> {
|
||||
let timeout = Duration::from_millis(1500);
|
||||
let mut gateway_client = GatewayClient::new_init(
|
||||
gateway.client_listener.clone(),
|
||||
gateway.clients_address(),
|
||||
gateway.identity_key,
|
||||
our_identity.clone(),
|
||||
timeout,
|
||||
@@ -91,45 +73,88 @@ async fn register_with_gateway(
|
||||
.await
|
||||
.expect("failed to establish connection with the gateway!");
|
||||
gateway_client
|
||||
.register()
|
||||
.perform_initial_authentication()
|
||||
.await
|
||||
.expect("failed to register with the gateway!")
|
||||
}
|
||||
|
||||
async fn gateway_details(validator_server: &str, chosen_gateway_id: Option<&str>) -> gateway::Node {
|
||||
let validator_client_config = validator_client::Config::new(validator_server.to_string());
|
||||
let validator_client = validator_client::Client::new(validator_client_config);
|
||||
let topology = validator_client.get_active_topology().await.unwrap();
|
||||
let nym_topology: NymTopology = topology.into();
|
||||
let version_filtered_topology = nym_topology.filter_system_version(env!("CARGO_PKG_VERSION"));
|
||||
async fn gateway_details(
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<&str>,
|
||||
) -> gateway::Node {
|
||||
let validator_api = validator_servers
|
||||
.choose(&mut thread_rng())
|
||||
.expect("The list of validator apis is empty");
|
||||
let validator_client = validator_client::ApiClient::new(validator_api.clone());
|
||||
|
||||
let gateways = validator_client.get_cached_gateways().await.unwrap();
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
.collect::<Vec<gateway::Node>>();
|
||||
|
||||
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
|
||||
|
||||
// if we have chosen particular gateway - use it, otherwise choose a random one.
|
||||
// (remember that in active topology all gateways have at least 100 reputation so should
|
||||
// be working correctly)
|
||||
|
||||
if let Some(gateway_id) = chosen_gateway_id {
|
||||
version_filtered_topology
|
||||
.gateways()
|
||||
filtered_gateways
|
||||
.iter()
|
||||
.find(|gateway| gateway.identity_key.to_base58_string() == gateway_id)
|
||||
.expect(&*format!("no gateway with id {} exists!", gateway_id))
|
||||
.clone()
|
||||
} else {
|
||||
version_filtered_topology
|
||||
.gateways()
|
||||
filtered_gateways
|
||||
.choose(&mut rand::thread_rng())
|
||||
.expect("there are no gateways on the network!")
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn show_address(config: &Config) {
|
||||
fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair {
|
||||
let identity_keypair: identity::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
pathfinder.public_identity_key().to_owned(),
|
||||
))
|
||||
.expect("Failed to read stored identity key files");
|
||||
identity_keypair
|
||||
}
|
||||
|
||||
fn load_sphinx_keys(pathfinder: &ClientKeyPathfinder) -> encryption::KeyPair {
|
||||
let sphinx_keypair: encryption::KeyPair =
|
||||
pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_encryption_key().to_owned(),
|
||||
pathfinder.public_encryption_key().to_owned(),
|
||||
))
|
||||
.expect("Failed to read stored sphinx key files");
|
||||
sphinx_keypair
|
||||
}
|
||||
|
||||
let pathfinder = ClientKeyPathfinder::new_from_config(config.get_base());
|
||||
let identity_keypair = load_identity_keys(&pathfinder);
|
||||
let sphinx_keypair = load_sphinx_keys(&pathfinder);
|
||||
|
||||
let client_recipient = Recipient::new(
|
||||
*identity_keypair.public_key(),
|
||||
*sphinx_keypair.public_key(),
|
||||
// TODO: below only works under assumption that gateway address == gateway id
|
||||
// (which currently is true)
|
||||
NodeIdentity::from_base58_string(config.get_base().get_gateway_id()).unwrap(),
|
||||
);
|
||||
|
||||
println!("\nThe address of this client is: {}", client_recipient);
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
println!("Initialising client...");
|
||||
|
||||
let id = matches.value_of("id").unwrap(); // required for now
|
||||
let provider_address = matches.value_of("provider").unwrap();
|
||||
|
||||
let already_init = if Config::default_config_file_path(id).exists() {
|
||||
let already_init = if Config::default_config_file_path(Some(id)).exists() {
|
||||
println!("Socks5 client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
|
||||
true
|
||||
} else {
|
||||
@@ -157,7 +182,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
let registration_fut = async {
|
||||
let gate_details = gateway_details(
|
||||
&config.get_base().get_validator_rest_endpoint(),
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
@@ -166,11 +191,11 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.with_gateway_id(gate_details.identity_key.to_base58_string());
|
||||
let shared_keys =
|
||||
register_with_gateway(&gate_details, key_manager.identity_keypair()).await;
|
||||
(shared_keys, gate_details.client_listener)
|
||||
(shared_keys, gate_details.clients_address())
|
||||
};
|
||||
|
||||
// TODO: is there perhaps a way to make it work without having to spawn entire runtime?
|
||||
let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let (shared_keys, gateway_listener) = rt.block_on(registration_fut);
|
||||
config
|
||||
.get_base_mut()
|
||||
@@ -190,5 +215,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.expect("Failed to save the config file");
|
||||
println!("Saved configuration file to {:?}", config_save_location);
|
||||
println!("Using gateway: {}", config.get_base().get_gateway_id(),);
|
||||
println!("Client configuration completed.\n\n\n")
|
||||
println!("Client configuration completed.\n\n\n");
|
||||
|
||||
show_address(&config);
|
||||
}
|
||||
|
||||
@@ -1,37 +1,36 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::Config;
|
||||
use clap::ArgMatches;
|
||||
use url::Url;
|
||||
|
||||
pub(crate) mod init;
|
||||
pub(crate) mod run;
|
||||
pub(crate) mod upgrade;
|
||||
|
||||
fn parse_validators(raw: &str) -> Vec<Url> {
|
||||
raw.split(',')
|
||||
.map(|raw_validator| {
|
||||
raw_validator
|
||||
.trim()
|
||||
.parse()
|
||||
.expect("one of the provided validator api urls is invalid")
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
|
||||
if let Some(validator) = matches.value_of("validator") {
|
||||
config.get_base_mut().set_custom_validator(validator);
|
||||
if let Some(raw_validators) = matches.value_of("validators") {
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(parse_validators(raw_validators));
|
||||
}
|
||||
|
||||
if let Some(gateway_id) = matches.value_of("gateway") {
|
||||
config.get_base_mut().with_gateway_id(gateway_id);
|
||||
}
|
||||
|
||||
if matches.is_present("vpn-mode") {
|
||||
config.get_base_mut().set_vpn_mode(true);
|
||||
}
|
||||
|
||||
if let Some(port) = matches.value_of("port").map(|port| port.parse::<u16>()) {
|
||||
if let Err(err) = port {
|
||||
// if port was overridden, it must be parsable
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::Config;
|
||||
use crate::client::NymClient;
|
||||
@@ -40,27 +29,16 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
.help("Address of the socks5 provider to send messages to.")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(Arg::with_name("validator")
|
||||
.long("validator")
|
||||
.help("Address of the validator server the client is getting topology from")
|
||||
.takes_value(true),
|
||||
.arg(Arg::with_name("validators")
|
||||
.long("validators")
|
||||
.help("Comma separated list of rest endpoints of the validators")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(Arg::with_name("gateway")
|
||||
.long("gateway")
|
||||
.help("Id of the gateway we want to connect to. If overridden, it is user's responsibility to ensure prior registration happened")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(Arg::with_name("vpn-mode")
|
||||
.long("vpn-mode")
|
||||
.help("Set the vpn mode of the client")
|
||||
.long_help(
|
||||
r#"
|
||||
Special mode of the system such that all messages are sent as soon as they are received
|
||||
and no cover traffic is generated. If set all message delays are set to 0 and overwriting
|
||||
'Debug' values will have no effect.
|
||||
"#
|
||||
)
|
||||
)
|
||||
.arg(Arg::with_name("port")
|
||||
.short("p")
|
||||
.long("port")
|
||||
@@ -91,7 +69,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let id = matches.value_of("id").unwrap();
|
||||
|
||||
let mut config = match Config::load_from_file(id) {
|
||||
let mut config = match Config::load_from_file(Some(id)) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})", id, err);
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::{Config, MISSING_VALUE};
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use client_core::config::DEFAULT_VALIDATOR_REST_ENDPOINT;
|
||||
use config::defaults::default_api_endpoints;
|
||||
use config::NymConfig;
|
||||
use std::fmt::Display;
|
||||
use std::process;
|
||||
use version_checker::{parse_version, Version};
|
||||
use version_checker::Version;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn fail_upgrade<D1: Display, D2: Display>(from_version: D1, to_version: D2) -> ! {
|
||||
print_failed_upgrade(from_version, to_version);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
fn print_start_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
|
||||
println!(
|
||||
"\n==================\nTrying to upgrade mixnode from {} to {} ...",
|
||||
"\n==================\nTrying to upgrade client from {} to {} ...",
|
||||
from, to
|
||||
);
|
||||
}
|
||||
@@ -41,147 +36,136 @@ fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
|
||||
);
|
||||
}
|
||||
|
||||
fn pre_090_upgrade(from: &str, mut config: Config) -> Config {
|
||||
// this is not extracted to separate function as you only have to manually pass version
|
||||
// if upgrading from pre090 version
|
||||
let from = match from.strip_prefix("v") {
|
||||
Some(stripped) => stripped,
|
||||
None => from,
|
||||
};
|
||||
fn outdated_upgrade(config_version: &Version, package_version: &Version) -> ! {
|
||||
eprintln!(
|
||||
"Cannot perform upgrade from {} to {}. Your version is too old to perform the upgrade.!",
|
||||
config_version, package_version
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
let from = match from.strip_prefix("V") {
|
||||
Some(stripped) => stripped,
|
||||
None => from,
|
||||
};
|
||||
fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! {
|
||||
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue if you expected it to work!", config_version, current_version);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
let from_version = parse_version(from).expect("invalid version provided!");
|
||||
if from_version.major == 0 && from_version.minor < 8 {
|
||||
// technically this could be implemented, but is there any point in that?
|
||||
eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead");
|
||||
pub fn command_args<'a, 'b>() -> App<'a, 'b> {
|
||||
App::new("upgrade").about("Try to upgrade the client").arg(
|
||||
Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-client we want to upgrade")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_config_version(config: &Config) -> Version {
|
||||
let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse client version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
if version.is_prerelease() || !version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade from a non-released version {}. This is not supported!",
|
||||
version
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 {
|
||||
eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version");
|
||||
version
|
||||
}
|
||||
|
||||
fn parse_package_version() -> Version {
|
||||
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
|
||||
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
|
||||
// however, we are not using them ourselves at the moment and hence it should be fine.
|
||||
// if we change our mind, we could easily tweak this code
|
||||
if version.is_prerelease() || !version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade to a non-released version {}. This is not supported!",
|
||||
version
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
// note: current is guaranteed to not have any `build` information suffix (nor pre-release
|
||||
// information), as this was asserted at the beginning of this command)
|
||||
//
|
||||
// upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate
|
||||
// step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0)
|
||||
// this way we don't need to have all the crazy paths on how to upgrade from any version to any
|
||||
// other version. We just upgrade one minor version at a time.
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
let to_version = if current.major == 0 && current.minor == 9 {
|
||||
current
|
||||
version
|
||||
}
|
||||
|
||||
fn minor_0_12_upgrade(
|
||||
mut config: Config,
|
||||
_matches: &ArgMatches,
|
||||
config_version: &Version,
|
||||
package_version: &Version,
|
||||
) -> Config {
|
||||
let to_version = if package_version.major == 0 && package_version.minor == 12 {
|
||||
package_version.clone()
|
||||
} else {
|
||||
Version::new(0, 9, 0)
|
||||
Version::new(0, 12, 0)
|
||||
};
|
||||
|
||||
if config.get_base().get_validator_rest_endpoint() != MISSING_VALUE {
|
||||
eprintln!("existing config seems to have specified new validator rest endpoint which was only introduced in 0.9.0! Can't perform upgrade.");
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1);
|
||||
}
|
||||
print_start_upgrade(&config_version, &to_version);
|
||||
|
||||
print_start_upgrade(&from_version, &to_version);
|
||||
println!(
|
||||
"Setting validator API endpoints to {:?}",
|
||||
default_api_endpoints()
|
||||
);
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator_apis(default_api_endpoints());
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
println!(
|
||||
"Setting validator REST endpoint to to {}",
|
||||
DEFAULT_VALIDATOR_REST_ENDPOINT
|
||||
);
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_validator(DEFAULT_VALIDATOR_REST_ENDPOINT);
|
||||
|
||||
config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {:?}", err);
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
print_failed_upgrade(&config_version, &to_version);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(from_version, to_version);
|
||||
print_successful_upgrade(config_version, to_version);
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
pub fn command_args<'a, 'b>() -> App<'a, 'b> {
|
||||
App::new("upgrade").about("Try to upgrade the mixnode")
|
||||
.arg(
|
||||
Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-socks5-client we want to upgrade")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
// the rest of arguments depend on the upgrade path
|
||||
.arg(Arg::with_name("current version")
|
||||
.long("current-version")
|
||||
.help("REQUIRED FOR PRE-0.9.0 UPGRADES. Specifies current version of the configuration file to help to determine a valid upgrade path. Valid formats include '0.8.1', 'v0.8.1' or 'V0.8.1'")
|
||||
.takes_value(true)
|
||||
)
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version) {
|
||||
loop {
|
||||
let config_version = parse_config_version(&config);
|
||||
|
||||
if config_version == package_version {
|
||||
println!("You're using the most recent version!");
|
||||
return;
|
||||
}
|
||||
|
||||
config = match config_version.major {
|
||||
0 => match config_version.minor {
|
||||
9 | 10 => outdated_upgrade(&config_version, &package_version),
|
||||
11 => minor_0_12_upgrade(config, matches, &config_version, &package_version),
|
||||
_ => unsupported_upgrade(&config_version, &package_version),
|
||||
},
|
||||
_ => unsupported_upgrade(&config_version, &package_version),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
|
||||
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
|
||||
// however, we are not using them ourselves at the moment and hence it should be fine.
|
||||
// if we change our mind, we could easily tweak this code
|
||||
if current.is_prerelease() || !current.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade to a non-released version {}. This is not supported!",
|
||||
current
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
let package_version = parse_package_version();
|
||||
|
||||
let id = matches.value_of("id").unwrap();
|
||||
|
||||
let mut existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
|
||||
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
|
||||
eprintln!("failed to load existing config file! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
// versions fields were added in 0.9.0
|
||||
if existing_config.get_base().get_version() == MISSING_VALUE {
|
||||
let self_reported_version = matches.value_of("current version").unwrap_or_else(|| {
|
||||
eprintln!(
|
||||
"trying to upgrade from pre v0.9.0 without providing current system version!"
|
||||
);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
// upgrades up to 0.9.0
|
||||
existing_config = pre_090_upgrade(self_reported_version, existing_config);
|
||||
eprintln!("the existing configuration file does not seem to contain version number.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let config_version =
|
||||
Version::parse(existing_config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse node version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
if config_version.is_prerelease() || !config_version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade to from non-released version {}. This is not supported!",
|
||||
current
|
||||
);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
// here be upgrade path to 0.10.0 and beyond based on version number from config
|
||||
if config_version == current {
|
||||
println!("You're using the most recent version!");
|
||||
} else {
|
||||
eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue!", config_version, current);
|
||||
process::exit(1)
|
||||
}
|
||||
// here be upgrade path to 0.9.X and beyond based on version number from config
|
||||
do_upgrade(existing_config, matches, package_version)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod client;
|
||||
pub mod socks;
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{App, ArgMatches};
|
||||
|
||||
|
||||
@@ -51,9 +51,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn constructor_works() {
|
||||
let mut auth_methods: Vec<u8> = Vec::new();
|
||||
auth_methods.push(AuthenticationMethods::NoAuth as u8);
|
||||
auth_methods.push(AuthenticationMethods::UserPass as u8);
|
||||
let auth_methods = vec![
|
||||
AuthenticationMethods::NoAuth as u8,
|
||||
AuthenticationMethods::UserPass as u8,
|
||||
];
|
||||
|
||||
let admin = User {
|
||||
username: "foo".to_string(),
|
||||
@@ -98,8 +99,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn allowed_user_passes_authentication_check() {
|
||||
let mut auth_methods: Vec<u8> = Vec::new();
|
||||
auth_methods.push(AuthenticationMethods::UserPass as u8);
|
||||
let auth_methods = vec![AuthenticationMethods::UserPass as u8];
|
||||
|
||||
let admin = User {
|
||||
username: "foo".to_string(),
|
||||
@@ -115,8 +115,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn disallowed_user_fails_authentication_check() {
|
||||
let mut auth_methods: Vec<u8> = Vec::new();
|
||||
auth_methods.push(AuthenticationMethods::UserPass as u8);
|
||||
let auth_methods = vec![AuthenticationMethods::UserPass as u8];
|
||||
|
||||
let bad_user = User {
|
||||
username: "ashy".to_string(),
|
||||
|
||||
@@ -17,9 +17,10 @@ use proxy_helpers::connection_controller::{
|
||||
use proxy_helpers::proxy_runner::ProxyRunner;
|
||||
use rand::RngCore;
|
||||
use socks5_requests::{ConnectionId, RemoteAddress, Request};
|
||||
use std::net::{Shutdown, SocketAddr};
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use std::pin::Pin;
|
||||
use tokio::prelude::*;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf};
|
||||
use tokio::{self, net::TcpStream};
|
||||
|
||||
#[pin_project(project = StateProject)]
|
||||
@@ -61,12 +62,12 @@ impl StreamState {
|
||||
}
|
||||
}
|
||||
|
||||
fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
async fn shutdown(&mut self) -> io::Result<()> {
|
||||
// shutdown should only be called if proxy is not being run. If it is, there's some bug
|
||||
// somewhere
|
||||
match self {
|
||||
StreamState::RunningProxy => panic!("Tried to shutdown stream while proxy is running"),
|
||||
StreamState::Available(ref stream) => TcpStream::shutdown(stream, how),
|
||||
StreamState::Available(ref mut stream) => TcpStream::shutdown(stream).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,8 +77,8 @@ impl AsyncRead for StreamState {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<io::Result<()>> {
|
||||
match self.project() {
|
||||
StateProject::RunningProxy => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
@@ -138,15 +139,18 @@ pub(crate) struct SocksClient {
|
||||
connection_id: ConnectionId,
|
||||
service_provider: Recipient,
|
||||
self_address: Recipient,
|
||||
started_proxy: bool,
|
||||
}
|
||||
|
||||
impl Drop for SocksClient {
|
||||
fn drop(&mut self) {
|
||||
// TODO: decrease to debug/trace
|
||||
debug!("Connection {} is getting closed", self.connection_id);
|
||||
self.controller_sender
|
||||
.unbounded_send(ControllerCommand::Remove(self.connection_id))
|
||||
.unwrap();
|
||||
// if we never managed to start a proxy, the entry will not exist in the controller
|
||||
if self.started_proxy {
|
||||
self.controller_sender
|
||||
.unbounded_send(ControllerCommand::Remove(self.connection_id))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +175,7 @@ impl SocksClient {
|
||||
input_sender,
|
||||
service_provider,
|
||||
self_address,
|
||||
started_proxy: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,9 +191,9 @@ impl SocksClient {
|
||||
}
|
||||
|
||||
/// Shutdown the TcpStream to the client and end the session
|
||||
pub fn shutdown(&mut self) -> Result<(), SocksProxyError> {
|
||||
pub async fn shutdown(&mut self) -> Result<(), SocksProxyError> {
|
||||
info!("client is shutting down its TCP stream");
|
||||
self.stream.shutdown(Shutdown::Both)?;
|
||||
self.stream.shutdown().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -206,28 +211,21 @@ impl SocksClient {
|
||||
// Handle SOCKS4 requests
|
||||
if header[0] != SOCKS_VERSION {
|
||||
warn!("Init: Unsupported version: SOCKS{}", self.socks_version);
|
||||
self.shutdown()?;
|
||||
self.shutdown().await
|
||||
}
|
||||
// Valid SOCKS5
|
||||
else {
|
||||
// Authenticate w/ client
|
||||
self.authenticate().await?;
|
||||
// Handle requests
|
||||
self.handle_request().await?;
|
||||
self.handle_request().await
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_connect_to_mixnet(&mut self, remote_address: RemoteAddress) {
|
||||
let req = Request::new_connect(
|
||||
self.connection_id,
|
||||
remote_address.clone(),
|
||||
self.self_address.clone(),
|
||||
);
|
||||
let req = Request::new_connect(self.connection_id, remote_address, self.self_address);
|
||||
|
||||
let input_message =
|
||||
InputMessage::new_fresh(self.service_provider.clone(), req.into_bytes(), false);
|
||||
let input_message = InputMessage::new_fresh(self.service_provider, req.into_bytes(), false);
|
||||
self.input_sender.unbounded_send(input_message).unwrap();
|
||||
}
|
||||
|
||||
@@ -272,16 +270,17 @@ impl SocksClient {
|
||||
// setup for receiving from the mixnet
|
||||
let (mix_sender, mix_receiver) = mpsc::unbounded();
|
||||
|
||||
self.controller_sender
|
||||
.unbounded_send(ControllerCommand::Insert(self.connection_id, mix_sender))
|
||||
.unwrap();
|
||||
|
||||
match request.command {
|
||||
// Use the Proxy to connect to the specified addr/port
|
||||
SocksCommand::Connect => {
|
||||
trace!("Connecting to: {:?}", remote_address.clone());
|
||||
self.acknowledge_socks5().await;
|
||||
|
||||
self.started_proxy = true;
|
||||
self.controller_sender
|
||||
.unbounded_send(ControllerCommand::Insert(self.connection_id, mix_sender))
|
||||
.unwrap();
|
||||
|
||||
info!(
|
||||
"Starting proxy for {} (id: {})",
|
||||
remote_address.clone(),
|
||||
@@ -326,7 +325,7 @@ impl SocksClient {
|
||||
/// username and password from the stream, then check with the Authenticator
|
||||
/// to see if the resulting user is allowed.
|
||||
///
|
||||
/// A lot of this could probably be put into the the `SocksRequest::from_stream()`
|
||||
/// A lot of this could probably be put into the `SocksRequest::from_stream()`
|
||||
/// constructor, and/or cleaned up with tokio::codec. It's mostly just
|
||||
/// read-a-byte-or-two. The bytes being extracted look like this:
|
||||
///
|
||||
@@ -392,7 +391,7 @@ impl SocksClient {
|
||||
self.stream.write_all(&response).await?;
|
||||
|
||||
// Shutdown
|
||||
self.shutdown()?;
|
||||
self.shutdown().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -406,7 +405,7 @@ impl SocksClient {
|
||||
warn!("Client has no suitable authentication methods!");
|
||||
response[1] = AuthenticationMethods::NoMethods as u8;
|
||||
self.stream.write_all(&response).await?;
|
||||
self.shutdown()?;
|
||||
self.shutdown().await?;
|
||||
Err(ResponseCode::Failure.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ impl MixnetResponseListener {
|
||||
.unwrap();
|
||||
|
||||
MixnetResponseListener {
|
||||
controller_sender,
|
||||
buffer_requester,
|
||||
mix_response_receiver,
|
||||
controller_sender,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@ use super::types::{AddrType, ResponseCode, SocksProxyError};
|
||||
use super::{utils as socks_utils, SOCKS_VERSION};
|
||||
use log::*;
|
||||
use std::fmt::{self, Display};
|
||||
use tokio::prelude::*;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
||||
|
||||
/// A Socks5 request hitting the proxy.
|
||||
pub(crate) struct SocksRequest {
|
||||
#[allow(dead_code)]
|
||||
pub version: u8,
|
||||
pub command: SocksCommand,
|
||||
pub addr_type: AddrType,
|
||||
|
||||
@@ -48,7 +48,7 @@ impl SphinxSocksServer {
|
||||
input_sender: InputMessageSender,
|
||||
buffer_requester: ReceivedBufferRequestSender,
|
||||
) -> Result<(), SocksProxyError> {
|
||||
let mut listener = TcpListener::bind(self.listening_address).await.unwrap();
|
||||
let listener = TcpListener::bind(self.listening_address).await.unwrap();
|
||||
info!("Serving Connections...");
|
||||
|
||||
// controller for managing all active connections
|
||||
@@ -100,7 +100,7 @@ impl SphinxSocksServer {
|
||||
if client.error(response).await.is_err() {
|
||||
warn!("Failed to send error code");
|
||||
};
|
||||
if client.shutdown().is_err() {
|
||||
if client.shutdown().await.is_err() {
|
||||
warn!("Failed to shutdown TcpStream");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
/node_modules/
|
||||
/src/node_modules/@sapper/
|
||||
yarn-error.log
|
||||
/__sapper__/
|
||||
@@ -0,0 +1,33 @@
|
||||
## Prerequisites
|
||||
|
||||
On Ubuntu-ish systems (not tested on Debian but may work):
|
||||
|
||||
```
|
||||
sudo apt update && sudo apt install libwebkit2gtk-4.0-dev \
|
||||
build-essential \
|
||||
curl \
|
||||
wget \
|
||||
libssl-dev \
|
||||
libgtk-3-dev \
|
||||
libappindicator3-dev \
|
||||
patchelf \
|
||||
librsvg2-dev```
|
||||
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Start Sapper([docs](https://sapper.svelte.dev/docs/)) -> `yarn run dev`
|
||||
2. Start Tauri([docs](https://tauri.studio/en/)) in another terminal -> `yarn tauri dev`
|
||||
3. Start validator-api locally, or override `validator-urls` in `index.svelte`
|
||||
|
||||
## Getting around
|
||||
|
||||
+ Frontend -> `tauri-client/`
|
||||
+ logic -> `tauri-client/src/routes/index.svelte`
|
||||
+ assets -> `tauri-client/static`
|
||||
+ Backend -> `tauri-client/src/src-tauri`
|
||||
|
||||
## Build standalone app
|
||||
|
||||
+ yarn tauri build [--debug]
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "TODO",
|
||||
"description": "TODO",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "sapper dev",
|
||||
"build": "sapper build --legacy",
|
||||
"export": "sapper export --legacy",
|
||||
"start": "node __sapper__/build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.0.0-beta.4",
|
||||
"compression": "^1.7.1",
|
||||
"polka": "next",
|
||||
"qrious": "^4.0.2",
|
||||
"sirv": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@rollup/plugin-babel": "^5.0.0",
|
||||
"@rollup/plugin-commonjs": "^14.0.0",
|
||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||
"@rollup/plugin-replace": "^2.4.0",
|
||||
"@rollup/plugin-url": "^5.0.0",
|
||||
"@tauri-apps/cli": "^1.0.0-beta.5",
|
||||
"rollup": "^2.3.4",
|
||||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"sapper": "^0.28.0",
|
||||
"sass": "^1.35.2",
|
||||
"svelte": "^3.17.3",
|
||||
"svelte-preprocess": "^4.7.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import path from "path";
|
||||
import resolve from "@rollup/plugin-node-resolve";
|
||||
import replace from "@rollup/plugin-replace";
|
||||
import commonjs from "@rollup/plugin-commonjs";
|
||||
import url from "@rollup/plugin-url";
|
||||
import svelte from "rollup-plugin-svelte";
|
||||
import babel from "@rollup/plugin-babel";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
import config from "sapper/config/rollup.js";
|
||||
import pkg from "./package.json";
|
||||
import sveltePreprocess from "svelte-preprocess";
|
||||
|
||||
const mode = process.env.NODE_ENV;
|
||||
const dev = mode === "development";
|
||||
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
|
||||
|
||||
const onwarn = (warning, onwarn) =>
|
||||
(warning.code === "MISSING_EXPORT" && /'preload'/.test(warning.message)) ||
|
||||
(warning.code === "CIRCULAR_DEPENDENCY" &&
|
||||
/[/\\]@sapper[/\\]/.test(warning.message)) ||
|
||||
onwarn(warning);
|
||||
|
||||
export default {
|
||||
client: {
|
||||
input: config.client.input(),
|
||||
output: config.client.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
values: {
|
||||
"process.browser": true,
|
||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
||||
},
|
||||
}),
|
||||
svelte({
|
||||
compilerOptions: {
|
||||
dev,
|
||||
hydratable: true,
|
||||
},
|
||||
preprocess: sveltePreprocess(),
|
||||
}),
|
||||
url({
|
||||
sourceDir: path.resolve(__dirname, "src/node_modules/images"),
|
||||
publicPath: "/client/",
|
||||
}),
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ["svelte"],
|
||||
}),
|
||||
commonjs(),
|
||||
|
||||
legacy &&
|
||||
babel({
|
||||
extensions: [".js", ".mjs", ".html", ".svelte"],
|
||||
babelHelpers: "runtime",
|
||||
exclude: ["node_modules/@babel/**"],
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
targets: "> 0.25%, not dead",
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
[
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
useESModules: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
|
||||
!dev &&
|
||||
terser({
|
||||
module: true,
|
||||
}),
|
||||
],
|
||||
|
||||
preserveEntrySignatures: false,
|
||||
onwarn,
|
||||
},
|
||||
|
||||
server: {
|
||||
input: config.server.input(),
|
||||
output: config.server.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
values: {
|
||||
"process.browser": false,
|
||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
||||
},
|
||||
}),
|
||||
svelte({
|
||||
compilerOptions: {
|
||||
dev,
|
||||
generate: "ssr",
|
||||
hydratable: true,
|
||||
},
|
||||
emitCss: false,
|
||||
}),
|
||||
url({
|
||||
sourceDir: path.resolve(__dirname, "src/node_modules/images"),
|
||||
publicPath: "/client/",
|
||||
emitFiles: false, // already emitted by client build
|
||||
}),
|
||||
resolve({
|
||||
dedupe: ["svelte"],
|
||||
}),
|
||||
commonjs(),
|
||||
],
|
||||
external: Object.keys(pkg.dependencies).concat(
|
||||
require("module").builtinModules
|
||||
),
|
||||
preserveEntrySignatures: "strict",
|
||||
onwarn,
|
||||
},
|
||||
|
||||
serviceworker: {
|
||||
input: config.serviceworker.input(),
|
||||
output: config.serviceworker.output(),
|
||||
plugins: [
|
||||
resolve(),
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
values: {
|
||||
"process.browser": true,
|
||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
||||
},
|
||||
}),
|
||||
commonjs(),
|
||||
!dev && terser(),
|
||||
],
|
||||
preserveEntrySignatures: false,
|
||||
onwarn,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* Run this script to convert the project to TypeScript. This is only guaranteed to work
|
||||
* on the unmodified default template; if you have done code changes you are likely need
|
||||
* to touch up the generated project manually.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { argv } = require('process');
|
||||
|
||||
const projectRoot = argv[2] || path.join(__dirname, '..');
|
||||
|
||||
const isRollup = fs.existsSync(path.join(projectRoot, "rollup.config.js"));
|
||||
|
||||
function warn(message) {
|
||||
console.warn('Warning: ' + message);
|
||||
}
|
||||
|
||||
function replaceInFile(fileName, replacements) {
|
||||
if (fs.existsSync(fileName)) {
|
||||
let contents = fs.readFileSync(fileName, 'utf8');
|
||||
let hadUpdates = false;
|
||||
|
||||
replacements.forEach(([from, to]) => {
|
||||
const newContents = contents.replace(from, to);
|
||||
|
||||
const isAlreadyApplied = typeof to !== 'string' || contents.includes(to);
|
||||
|
||||
if (newContents !== contents) {
|
||||
contents = newContents;
|
||||
hadUpdates = true;
|
||||
} else if (!isAlreadyApplied) {
|
||||
warn(`Wanted to update "${from}" in ${fileName}, but did not find it.`);
|
||||
}
|
||||
});
|
||||
|
||||
if (hadUpdates) {
|
||||
fs.writeFileSync(fileName, contents);
|
||||
} else {
|
||||
console.log(`${fileName} had already been updated.`);
|
||||
}
|
||||
} else {
|
||||
warn(`Wanted to update ${fileName} but the file did not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
function createFile(fileName, contents) {
|
||||
if (fs.existsSync(fileName)) {
|
||||
warn(`Wanted to create ${fileName}, but it already existed. Leaving existing file.`);
|
||||
} else {
|
||||
fs.writeFileSync(fileName, contents);
|
||||
}
|
||||
}
|
||||
|
||||
function addDepsToPackageJson() {
|
||||
const pkgJSONPath = path.join(projectRoot, 'package.json');
|
||||
const packageJSON = JSON.parse(fs.readFileSync(pkgJSONPath, 'utf8'));
|
||||
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
|
||||
...(isRollup ? { '@rollup/plugin-typescript': '^6.0.0' } : { 'ts-loader': '^8.0.4' }),
|
||||
'@tsconfig/svelte': '^1.0.10',
|
||||
'@types/compression': '^1.7.0',
|
||||
'@types/node': '^14.11.1',
|
||||
'@types/polka': '^0.5.1',
|
||||
'svelte-check': '^1.0.46',
|
||||
'svelte-preprocess': '^4.3.0',
|
||||
tslib: '^2.0.1',
|
||||
typescript: '^4.0.3'
|
||||
});
|
||||
|
||||
// Add script for checking
|
||||
packageJSON.scripts = Object.assign(packageJSON.scripts, {
|
||||
validate: 'svelte-check --ignore src/node_modules/@sapper'
|
||||
});
|
||||
|
||||
// Write the package JSON
|
||||
fs.writeFileSync(pkgJSONPath, JSON.stringify(packageJSON, null, ' '));
|
||||
}
|
||||
|
||||
function changeJsExtensionToTs(dir) {
|
||||
const elements = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
if (elements[i].isDirectory()) {
|
||||
changeJsExtensionToTs(path.join(dir, elements[i].name));
|
||||
} else if (elements[i].name.match(/^[^_]((?!json).)*js$/)) {
|
||||
fs.renameSync(path.join(dir, elements[i].name), path.join(dir, elements[i].name).replace('.js', '.ts'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateSingleSvelteFile({ view, vars, contextModule }) {
|
||||
replaceInFile(path.join(projectRoot, 'src', `${view}.svelte`), [
|
||||
[/(?:<script)(( .*?)*?)>/gm, (m, attrs) => `<script${attrs}${!attrs.includes('lang="ts"') ? ' lang="ts"' : ''}>`],
|
||||
...(vars ? vars.map(({ name, type }) => [`export let ${name};`, `export let ${name}: ${type};`]) : []),
|
||||
...(contextModule ? contextModule.map(({ js, ts }) => [js, ts]) : [])
|
||||
]);
|
||||
}
|
||||
|
||||
// Switch the *.svelte file to use TS
|
||||
function updateSvelteFiles() {
|
||||
[
|
||||
{
|
||||
view: 'components/Nav',
|
||||
vars: [{ name: 'segment', type: 'string' }]
|
||||
},
|
||||
{
|
||||
view: 'routes/_layout',
|
||||
vars: [{ name: 'segment', type: 'string' }]
|
||||
},
|
||||
{
|
||||
view: 'routes/_error',
|
||||
vars: [
|
||||
{ name: 'status', type: 'number' },
|
||||
{ name: 'error', type: 'Error' }
|
||||
]
|
||||
},
|
||||
{
|
||||
view: 'routes/blog/index',
|
||||
vars: [{ name: 'posts', type: '{ slug: string; title: string, html: any }[]' }],
|
||||
contextModule: [
|
||||
{
|
||||
js: '.then(r => r.json())',
|
||||
ts: '.then((r: { json: () => any; }) => r.json())'
|
||||
},
|
||||
{
|
||||
js: '.then(posts => {',
|
||||
ts: '.then((posts: { slug: string; title: string, html: any }[]) => {'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
view: 'routes/blog/[slug]',
|
||||
vars: [{ name: 'post', type: '{ slug: string; title: string, html: any }' }]
|
||||
}
|
||||
].forEach(updateSingleSvelteFile);
|
||||
}
|
||||
|
||||
function updateRollupConfig() {
|
||||
// Edit rollup config
|
||||
replaceInFile(path.join(projectRoot, 'rollup.config.js'), [
|
||||
// Edit imports
|
||||
[
|
||||
/'rollup-plugin-terser';\n(?!import sveltePreprocess)/,
|
||||
`'rollup-plugin-terser';
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
`
|
||||
],
|
||||
// Edit inputs
|
||||
[
|
||||
/(?<!THIS_IS_UNDEFINED[^\n]*\n\s*)onwarn\(warning\);/,
|
||||
`(warning.code === 'THIS_IS_UNDEFINED') ||\n\tonwarn(warning);`
|
||||
],
|
||||
[/input: config.client.input\(\)(?!\.replace)/, `input: config.client.input().replace(/\\.js$/, '.ts')`],
|
||||
[
|
||||
/input: config.server.input\(\)(?!\.replace)/,
|
||||
`input: { server: config.server.input().server.replace(/\\.js$/, ".ts") }`
|
||||
],
|
||||
[
|
||||
/input: config.serviceworker.input\(\)(?!\.replace)/,
|
||||
`input: config.serviceworker.input().replace(/\\.js$/, '.ts')`
|
||||
],
|
||||
// Add preprocess
|
||||
[/compilerOptions/g, 'preprocess: sveltePreprocess({ sourceMap: dev }),\n\t\t\t\tcompilerOptions'],
|
||||
// Add TypeScript
|
||||
[/commonjs\(\)(?!,\n\s*typescript)/g, 'commonjs(),\n\t\t\ttypescript({ sourceMap: dev })']
|
||||
]);
|
||||
}
|
||||
|
||||
function updateWebpackConfig() {
|
||||
// Edit webpack config
|
||||
replaceInFile(path.join(projectRoot, 'webpack.config.js'), [
|
||||
// Edit imports
|
||||
[
|
||||
/require\('webpack-modules'\);\n(?!const sveltePreprocess)/,
|
||||
`require('webpack-modules');\nconst sveltePreprocess = require('svelte-preprocess');\n`
|
||||
],
|
||||
// Edit extensions
|
||||
[
|
||||
/\['\.mjs', '\.js', '\.json', '\.svelte', '\.html'\]/,
|
||||
`['.mjs', '.js', '.ts', '.json', '.svelte', '.html']`
|
||||
],
|
||||
// Edit entries
|
||||
[
|
||||
/entry: config\.client\.entry\(\)/,
|
||||
`entry: { main: config.client.entry().main.replace(/\\.js$/, '.ts') }`
|
||||
],
|
||||
[
|
||||
/entry: config\.server\.entry\(\)/,
|
||||
`entry: { server: config.server.entry().server.replace(/\\.js$/, '.ts') }`
|
||||
],
|
||||
[
|
||||
/entry: config\.serviceworker\.entry\(\)/,
|
||||
`entry: { 'service-worker': config.serviceworker.entry()['service-worker'].replace(/\\.js$/, '.ts') }`
|
||||
],
|
||||
[
|
||||
/loader: 'svelte-loader',\n\t\t\t\t\t\toptions: {/g,
|
||||
'loader: \'svelte-loader\',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tpreprocess: sveltePreprocess({ sourceMap: dev }),'
|
||||
],
|
||||
// Add TypeScript rules for client and server
|
||||
[
|
||||
/module: {\n\s*rules: \[\n\s*(?!{\n\s*test: \/\\\.ts\$\/)/g,
|
||||
`module: {\n\t\t\trules: [\n\t\t\t\t{\n\t\t\t\t\ttest: /\\.ts$/,\n\t\t\t\t\tloader: 'ts-loader'\n\t\t\t\t},\n\t\t\t\t`
|
||||
],
|
||||
// Add TypeScript rules for serviceworker
|
||||
[
|
||||
/output: config\.serviceworker\.output\(\),\n\s*(?!module)/,
|
||||
`output: config.serviceworker.output(),\n\t\tmodule: {\n\t\t\trules: [\n\t\t\t\t{\n\t\t\t\t\ttest: /\\.ts$/,\n\t\t\t\t\tloader: 'ts-loader'\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t`
|
||||
],
|
||||
// Edit outputs
|
||||
[
|
||||
/output: config\.serviceworker\.output\(\),\n\s*(?!resolve)/,
|
||||
`output: config.serviceworker.output(),\n\t\tresolve: { extensions: ['.mjs', '.js', '.ts', '.json'] },\n\t\t`
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
function updateServiceWorker() {
|
||||
replaceInFile(path.join(projectRoot, 'src', 'service-worker.ts'), [
|
||||
[`shell.concat(files);`, `(shell as string[]).concat(files as string[]);`],
|
||||
[`self.skipWaiting();`, `((self as any) as ServiceWorkerGlobalScope).skipWaiting();`],
|
||||
[`self.clients.claim();`, `((self as any) as ServiceWorkerGlobalScope).clients.claim();`],
|
||||
[`fetchAndCache(request)`, `fetchAndCache(request: Request)`],
|
||||
[`self.addEventListener('activate', event =>`, `self.addEventListener('activate', (event: ExtendableEvent) =>`],
|
||||
[`self.addEventListener('install', event =>`, `self.addEventListener('install', (event: ExtendableEvent) =>`],
|
||||
[`addEventListener('fetch', event =>`, `addEventListener('fetch', (event: FetchEvent) =>`],
|
||||
]);
|
||||
}
|
||||
|
||||
function createTsConfig() {
|
||||
const tsconfig = `{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM", "ES2017", "WebWorker"]
|
||||
},
|
||||
"include": ["src/**/*", "src/node_modules/**/*"],
|
||||
"exclude": ["node_modules/*", "__sapper__/*", "static/*"]
|
||||
}`;
|
||||
|
||||
createFile(path.join(projectRoot, 'tsconfig.json'), tsconfig);
|
||||
}
|
||||
|
||||
// Adds the extension recommendation
|
||||
function configureVsCode() {
|
||||
const dir = path.join(projectRoot, '.vscode');
|
||||
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
|
||||
createFile(path.join(projectRoot, '.vscode', 'extensions.json'), `{"recommendations": ["svelte.svelte-vscode"]}`);
|
||||
}
|
||||
|
||||
function deleteThisScript() {
|
||||
fs.unlinkSync(path.join(__filename));
|
||||
|
||||
// Check for Mac's DS_store file, and if it's the only one left remove it
|
||||
const remainingFiles = fs.readdirSync(path.join(__dirname));
|
||||
if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') {
|
||||
fs.unlinkSync(path.join(__dirname, '.DS_store'));
|
||||
}
|
||||
|
||||
// Check if the scripts folder is empty
|
||||
if (fs.readdirSync(path.join(__dirname)).length === 0) {
|
||||
// Remove the scripts folder
|
||||
fs.rmdirSync(path.join(__dirname));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Adding TypeScript with ${isRollup ? "Rollup" : "webpack" }...`);
|
||||
|
||||
addDepsToPackageJson();
|
||||
|
||||
changeJsExtensionToTs(path.join(projectRoot, 'src'));
|
||||
|
||||
updateSvelteFiles();
|
||||
|
||||
if (isRollup) {
|
||||
updateRollupConfig();
|
||||
} else {
|
||||
updateWebpackConfig();
|
||||
}
|
||||
|
||||
updateServiceWorker();
|
||||
|
||||
createTsConfig();
|
||||
|
||||
configureVsCode();
|
||||
|
||||
// Delete this script, but not during testing
|
||||
if (!argv[2]) {
|
||||
deleteThisScript();
|
||||
}
|
||||
|
||||
console.log('Converted to TypeScript.');
|
||||
|
||||
if (fs.existsSync(path.join(projectRoot, 'node_modules'))) {
|
||||
console.log(`
|
||||
Next:
|
||||
1. run 'npm install' again to install TypeScript dependencies
|
||||
2. run 'npm run build' for the @sapper imports in your project to work
|
||||
`);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
WixTools
|
||||
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
default-run = "app"
|
||||
edition = "2018"
|
||||
build = "src/build.rs"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.0.0-beta.2" }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.0.0-beta.4", features = [] }
|
||||
tokio = "1.4"
|
||||
url = "2.2"
|
||||
|
||||
coconut-interface = { path = "../../../common/coconut-interface" }
|
||||
credentials = { path = "../../../common/credentials" }
|
||||
validator-client = {path = "../../../common/client-libs/validator-client"}
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 7.2 KiB |