Compare commits
488 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8494eb83a | |||
| cb549dfe25 | |||
| 17507bc8c5 | |||
| 12f8e453ea | |||
| 97ef024b8a | |||
| 3dc94223ae | |||
| 50cd18a926 | |||
| 897d51cba0 | |||
| 1f1d91bd1e | |||
| 9d63a30b07 | |||
| 5b22b1c298 | |||
| 0302d9ae5d | |||
| eb6949528a | |||
| 41b77c3ad5 | |||
| 2f78f5eb26 | |||
| cdbd731f10 | |||
| 5cb4949d46 | |||
| 9ec0b30812 | |||
| 7e1cf2f105 | |||
| 04636a569a | |||
| 52f5b980a4 | |||
| 0e4f833715 | |||
| d22914c4dc | |||
| 7d506e6e2a | |||
| c7007de1ea | |||
| 10bf70b22b | |||
| d952f3233a | |||
| af4ac1b7c9 | |||
| eae4276381 | |||
| d8fab74df6 | |||
| b8c184cc60 | |||
| 8bcc931d9b | |||
| 955ef7b871 | |||
| 9ee7ad4fa8 | |||
| 79aa1febbe | |||
| 4ed9d3a297 | |||
| 97dee2e1a0 | |||
| 32c4974c44 | |||
| 5dadd73dfd | |||
| 6ad5badef4 | |||
| 480ad18b2e | |||
| cdb21f418b | |||
| bd4c18c723 | |||
| e7716ae852 | |||
| b19528d47e | |||
| ef88ce9252 | |||
| 488f1c7742 | |||
| 63c698d903 | |||
| 7e1c3b4501 | |||
| e1d7772a78 | |||
| 9db589e0b3 | |||
| 57c8d69785 | |||
| 4a9cc5b757 | |||
| 06aac9393b | |||
| f4c5b1d67f | |||
| 2e0aba6100 | |||
| 8c6549c5dd | |||
| 7b431ebfa8 | |||
| 3152fd6887 | |||
| e03e7f186a | |||
| ec056a548f | |||
| 24aa075a07 | |||
| 8488c4cb0f | |||
| 20c96b940f | |||
| cfb43699d6 | |||
| 79e7b5b938 | |||
| 47156e693c | |||
| b61f6c8833 | |||
| cc3b710af9 | |||
| 4de3f16bb3 | |||
| 7aad7daa5e | |||
| 4107d670cf | |||
| 284e797fb3 | |||
| 8a63df3e82 | |||
| 7b8731ddcc | |||
| 1017c9c642 | |||
| 4e0c59a8f1 | |||
| f6d85a0784 | |||
| 6516811276 | |||
| ca0ed3594f | |||
| a28ad4f81a | |||
| 0ea3183288 | |||
| c6ff7c51f0 | |||
| 0240ab6144 | |||
| 2746ec49a3 | |||
| b3f1c943a7 | |||
| 7654ede904 | |||
| c882487d01 | |||
| 865e4839f3 | |||
| 5a270f6489 | |||
| 6776bb4bab | |||
| cbe9bad66e | |||
| 5761e1c1a4 | |||
| 062a5edf76 | |||
| a009e76568 | |||
| dcc9b856d7 | |||
| 592e52b333 | |||
| bc923be862 | |||
| e880631500 | |||
| d9b0834476 | |||
| 2fda22e168 | |||
| a5091cd124 | |||
| b2ec19ece4 | |||
| 72e64cfab7 | |||
| 7eacb6b57e | |||
| e0e1ca992f | |||
| f1a628dee4 | |||
| 81d49dc4b9 | |||
| 7e581183f4 | |||
| a9f3fa0c72 | |||
| e6c5a97f8c | |||
| efb9b70293 | |||
| 666c233d6c | |||
| 4307756719 | |||
| 622d0d3ff9 | |||
| ad763c2131 | |||
| 87a2ec9468 | |||
| dd590e8779 | |||
| 9555f3a2cd | |||
| 0b79fc33d7 | |||
| b7e14489da | |||
| 84b426042e | |||
| f683b9e770 | |||
| 5fb2c9d822 | |||
| 0f7280c227 | |||
| 4ebca86a66 | |||
| 1a0c6eed27 | |||
| 673e13ec57 | |||
| 7caac334f4 | |||
| 4e0e081b3e | |||
| 51dc8c81ed | |||
| 727eedf7d3 | |||
| e37fddf3ab | |||
| 885679e575 | |||
| 36554c3c34 | |||
| 2197062372 | |||
| 487b894f3d | |||
| a03603b274 | |||
| e6879dba63 | |||
| 68a43e33b9 | |||
| db2ab41636 | |||
| c624327a7a | |||
| 32ff5cbc1e | |||
| 9ba203c7b3 | |||
| 729625ef4f | |||
| fd3923a5f9 | |||
| c2fd07ea18 | |||
| d76a2d84b5 | |||
| 2a98f7482d | |||
| 12637d93ff | |||
| f63aba9058 | |||
| 668325a4ce | |||
| 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 |
@@ -0,0 +1,40 @@
|
||||
# Lines starting with '#' are comments.
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
# More details are here: https://help.github.com/articles/about-codeowners/
|
||||
|
||||
# The '*' pattern is global owners.
|
||||
|
||||
# Order is important. The last matching pattern has the most precedence.
|
||||
# The folders are ordered as follows:
|
||||
|
||||
# In each subsection folders are ordered first by depth, then alphabetically.
|
||||
# This should make it easy to add new rules without breaking existing ones.
|
||||
|
||||
# Something weird not covered by anything else
|
||||
* @futurechimp @mmsinclair
|
||||
|
||||
# Rust rules:
|
||||
*.rs @durch @futurechimp @jstuczyn @neacsu
|
||||
Cargo.* @durch @futurechimp @jstuczyn @neacsu
|
||||
|
||||
# JS rules:
|
||||
*.js @mmsinclair @fmtabbara @Aid19801
|
||||
*.ts @mmsinclair @fmtabbara @Aid19801
|
||||
*.tsx @mmsinclair @fmtabbara @Aid19801
|
||||
*.jsx @mmsinclair @fmtabbara @Aid19801
|
||||
|
||||
# Something looking like possible documentation rules:
|
||||
*.md @mfahampshire
|
||||
|
||||
# our docker scripts
|
||||
/docker/ @neacsu
|
||||
|
||||
# if there are any changes in the core crypto, I feel like Ania should take a look:
|
||||
/common/crypto/ @aniampio
|
||||
/common/nymsphinx/ @aniampio
|
||||
|
||||
# Explorer and wallet should probably get looked by the product team
|
||||
/explorer/ @nymtech/product
|
||||
/nym-wallet/ @nymtech/product
|
||||
/wallet-web/ @nymtech/product
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an enhancement to the product
|
||||
title: "[Feature Request]"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is...
|
||||
|
||||
**Is your request a feature not related to an existing problem? A new feature.**
|
||||
For example.
|
||||
- Given I am using the nym wallet
|
||||
- When I transfer nym tokens across the network
|
||||
- Then I want to have an url link in the wallet which navigates outside the application to the nym-explorer
|
||||
|
||||
**Where does the feature fit in the Nym real estate?**
|
||||
- Application / UI
|
||||
|
||||
**What is this solving?**
|
||||
How will this improve the product...
|
||||
|
||||
**Is this an update to packages or libraries?**
|
||||
If so, please list them. If not, please ignore this section.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: Report
|
||||
about: To help identify and reproduce issues
|
||||
title: "[Issue]"
|
||||
labels: bug, bug-needs-triage, qa
|
||||
assignees: tommyv1987
|
||||
|
||||
---
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the issue is...
|
||||
|
||||
**Expected behaviour**
|
||||
A clear and concise description of what you expected to happen...
|
||||
|
||||
**Stack Traces**
|
||||
If there are stack traces or logs, please provide them here...
|
||||
|
||||
**Steps to Reproduce**
|
||||
Steps to reproduce the behaviour, if you're familiar with BDD syntax, please write it in this style:
|
||||
- Given I was doing X
|
||||
- And I installed Y
|
||||
- When I actioned Y
|
||||
- Then I expect Z
|
||||
|
||||
*An example:*
|
||||
- Given I was setting up a mix-node following the instructions in the docs
|
||||
- And I successfully bonded my node via the the wallet
|
||||
- When I went to start my mixnode
|
||||
- Then I was presented with an error
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem...
|
||||
|
||||
**Which area of Nym were you using?**
|
||||
- UI: [e.g. Websites - network-explorer, nym-website]
|
||||
- Application: [e.g Gateway, Client, Wallet]
|
||||
- OS: [e.g. Ubuntu 20.x, MacOs Big Sur, Windows 10]
|
||||
- Browser: [e.g Chrome (if applicable)]
|
||||
- Version: [e.g. nym binary(0.11.0), browser(94.0)]
|
||||
|
||||
**Additional context**
|
||||
Please provide any other information
|
||||
@@ -1,42 +1,102 @@
|
||||
name: Continuous integration
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'explorer/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'explorer/**'
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' }}
|
||||
strategy:
|
||||
matrix:
|
||||
rust: [stable, beta, nightly]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
matrix_prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
# creates the matrix strategy from build_matrix_includes.json
|
||||
- uses: actions/checkout@v2
|
||||
- id: set-matrix
|
||||
uses: JoshuaTheMiller/conditional-build-matrix@main
|
||||
with:
|
||||
inputFile: '.github/workflows/build_matrix_includes.json'
|
||||
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
|
||||
build:
|
||||
needs: matrix_prep
|
||||
strategy:
|
||||
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.os == '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-rs/toolchain@v1
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ matrix.rust }}
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
- name: Build all binaries
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --all
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
- name: Run all tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
name: Clippy checks
|
||||
# if: matrix.os == 'ubuntu-latest' && matrix.rust == 'stable'
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features
|
||||
|
||||
- name: Run clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
if: ${{ matrix.rust != 'nightly' }}
|
||||
with:
|
||||
command: clippy
|
||||
args: -- -D warnings
|
||||
args: -- -D warnings
|
||||
|
||||
# COCONUT stuff
|
||||
- name: Reclaim some disk space (because Windows is being annoying)
|
||||
uses: actions-rs/cargo@v1
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
with:
|
||||
command: clean
|
||||
|
||||
- name: Build all binaries with coconut enabled
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --all --features=coconut
|
||||
|
||||
- name: Run all tests with coconut enabled
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all --features=coconut
|
||||
|
||||
- name: Run clippy with coconut enabled
|
||||
uses: actions-rs/cargo@v1
|
||||
if: ${{ matrix.rust != 'nightly' }}
|
||||
with:
|
||||
command: clippy
|
||||
args: --features=coconut -- -D warnings
|
||||
@@ -0,0 +1,50 @@
|
||||
[
|
||||
{
|
||||
"os":"ubuntu-latest",
|
||||
"rust":"stable",
|
||||
"runOnEvent":"always"
|
||||
},
|
||||
|
||||
{
|
||||
"os":"windows-latest",
|
||||
"rust":"stable",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
{
|
||||
"os":"macos-latest",
|
||||
"rust":"stable",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
|
||||
{
|
||||
"os":"ubuntu-latest",
|
||||
"rust":"beta",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
{
|
||||
"os":"windows-latest",
|
||||
"rust":"beta",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
{
|
||||
"os":"macos-latest",
|
||||
"rust":"beta",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
|
||||
{
|
||||
"os":"ubuntu-latest",
|
||||
"rust":"nightly",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
{
|
||||
"os":"windows-latest",
|
||||
"rust":"nightly",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
{
|
||||
"os":"macos-latest",
|
||||
"rust":"nightly",
|
||||
"runOnEvent":"pull_request"
|
||||
}
|
||||
]
|
||||
@@ -1,14 +0,0 @@
|
||||
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,14 @@
|
||||
[
|
||||
{
|
||||
"rust":"stable",
|
||||
"runOnEvent":"always"
|
||||
},
|
||||
{
|
||||
"rust":"beta",
|
||||
"runOnEvent":"pull_request"
|
||||
},
|
||||
{
|
||||
"rust":"nightly",
|
||||
"runOnEvent":"pull_request"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,58 @@
|
||||
name: ERC20 Bridge Contract
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
matrix_prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
# creates the matrix strategy from build_matrix_includes.json
|
||||
- uses: actions/checkout@v2
|
||||
- id: set-matrix
|
||||
uses: JoshuaTheMiller/conditional-build-matrix@main
|
||||
with:
|
||||
inputFile: '.github/workflows/contract_matrix_includes.json'
|
||||
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
|
||||
erc20-bridge-contract:
|
||||
needs: matrix_prep
|
||||
strategy:
|
||||
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
|
||||
# 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' }}
|
||||
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
|
||||
env:
|
||||
RUSTFLAGS: '-C link-arg=-s'
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path contracts/erc20-bridge/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --manifest-path contracts/erc20-bridge/Cargo.toml
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path contracts/erc20-bridge/Cargo.toml -- --check
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
if: ${{ matrix.rust != 'nightly' }}
|
||||
with:
|
||||
command: clippy
|
||||
args: --manifest-path contracts/erc20-bridge/Cargo.toml -- -D warnings
|
||||
@@ -0,0 +1,64 @@
|
||||
name: Mixnet Contract
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'explorer/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'explorer/**'
|
||||
|
||||
jobs:
|
||||
matrix_prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
# creates the matrix strategy from build_matrix_includes.json
|
||||
- uses: actions/checkout@v2
|
||||
- id: set-matrix
|
||||
uses: JoshuaTheMiller/conditional-build-matrix@main
|
||||
with:
|
||||
inputFile: '.github/workflows/contract_matrix_includes.json'
|
||||
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
|
||||
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' }}
|
||||
needs: matrix_prep
|
||||
strategy:
|
||||
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
|
||||
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
|
||||
env:
|
||||
RUSTFLAGS: '-C link-arg=-s'
|
||||
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,23 @@
|
||||
name: Linting for Network Explorer (eslint/prettier)
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'explorer/**'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: explorer
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- run: npm install
|
||||
- name: Run ESLint
|
||||
# GitHub should automatically annotate the PR
|
||||
run: npm run lint
|
||||
@@ -0,0 +1,57 @@
|
||||
name: CI for Network Explorer
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'explorer/**'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: explorer
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- run: npm install
|
||||
continue-on-error: true
|
||||
- run: npm run test
|
||||
continue-on-error: true
|
||||
- run: npm run build
|
||||
continue-on-error: true
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "explorer/dist/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/network-explorer-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Keybase - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files/messages
|
||||
- name: Keybase - Send Notification
|
||||
env:
|
||||
NYM_PROJECT_NAME: "Network Explorer"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "network-explorer-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
|
||||
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
|
||||
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
|
||||
KEYBASE_NYM_CHANNEL: "ci-network-explorer"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/messages/entry_point_notifications.sh
|
||||
@@ -0,0 +1,77 @@
|
||||
name: Webdriverio tests for nym wallet
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "nym-wallet/**"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-wallet
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: wallet tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Tauri dependencies
|
||||
run: >
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y
|
||||
libgtk-3-dev
|
||||
libgtksourceview-3.0-dev
|
||||
webkit2gtk-4.0
|
||||
libappindicator3-dev
|
||||
webkit2gtk-driver
|
||||
xvfb
|
||||
|
||||
- name: Install minimal stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
|
||||
- name: Node v16
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Install yarn for building application
|
||||
run: yarn install
|
||||
|
||||
- name: Build application
|
||||
run: yarn run webpack:build & yarn run tauri:build
|
||||
|
||||
- name: Check binary exists
|
||||
run: |
|
||||
cd target/release/
|
||||
(test -f nym-wallet && echo nym binary exists) || echo wallet does not exist
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
working-directory: nym-wallet/webdriver
|
||||
|
||||
- name: Remove existing user datafile
|
||||
uses: JesseTG/rm@v1.0.2
|
||||
with:
|
||||
path: nym-wallet/webdriver/common/data/user-data.json
|
||||
|
||||
- name: Create user data json file
|
||||
id: create-json
|
||||
uses: jsdaniell/create-json@1.1.2
|
||||
with:
|
||||
name: "user-data.json"
|
||||
json: ${{ secrets.WALLET_USERDATA }}
|
||||
dir: "nym-wallet/webdriver/common/data/"
|
||||
|
||||
- name: Install tauri-driver
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: tauri-driver
|
||||
|
||||
- name: Launch tests
|
||||
run: xvfb-run yarn test:runall
|
||||
working-directory: nym-wallet/webdriver
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
.idea
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "all",
|
||||
"singleQuote": true,
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# pass exit codes out to GitHub Actions
|
||||
set -euxo pipefail
|
||||
|
||||
# change to the directory that contains this script
|
||||
cd "${0%/*}"
|
||||
|
||||
# run the node script
|
||||
node send_message.js
|
||||
@@ -0,0 +1,11 @@
|
||||
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||
> 🔴 **FAILURE** :cry:
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
|
||||
Commit message:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "send-keybase-message",
|
||||
"description": "Sends a notification message with the keybase package that fails when piped into the keybase CLI",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"format": "prettier --write send_message.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"handlebars": "^4.7.7",
|
||||
"keybase-bot": "^3.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "2.3.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
const Bot = require('keybase-bot');
|
||||
const Handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
|
||||
async function main() {
|
||||
const data = { env: process.env };
|
||||
// const data = { ...PASTE TEST DATA HERE ... }; // -- DEV: uncomment to set test data
|
||||
|
||||
// validation of environment
|
||||
if(!(process.env.NYM_PROJECT_NAME || data.env.NYM_PROJECT_NAME)) {
|
||||
throw new Error('Please set env var NYM_PROJECT_NAME with the project name for displaying in notification messages');
|
||||
}
|
||||
const keybaseChannel = process.env.KEYBASE_NYM_CHANNEL || data.env.KEYBASE_NYM_CHANNEL;
|
||||
if(!keybaseChannel) {
|
||||
throw new Error('Please set env var KEYBASE_NYM_CHANNEL with the channel name for the notification message');
|
||||
}
|
||||
|
||||
// extract the git branch name
|
||||
const GIT_BRANCH_NAME = (process.env.GITHUB_REF || data.env.GITHUB_REF).split('/').slice(2).join('/');
|
||||
|
||||
data.env.GIT_BRANCH_NAME = GIT_BRANCH_NAME;
|
||||
const source = fs
|
||||
.readFileSync(process.env.IS_SUCCESS === 'true' ? 'success' : 'failure')
|
||||
.toString();
|
||||
const template = Handlebars.compile(source);
|
||||
const result = template(data);
|
||||
|
||||
// -- DEV: uncomment to show what is available in the handlebars template / show the result
|
||||
// console.dir({ data }, { depth: null });
|
||||
// console.log(result);
|
||||
|
||||
const bot = new Bot();
|
||||
try {
|
||||
const username = process.env.KEYBASE_NYMBOT_USERNAME;
|
||||
const paperkey = process.env.KEYBASE_NYMBOT_PAPERKEY;
|
||||
|
||||
if(!username) {
|
||||
throw new Error('Username is not defined. Please set env var KEYBASE_NYMBOT_USERNAME');
|
||||
}
|
||||
if(!paperkey) {
|
||||
throw new Error('Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY');
|
||||
}
|
||||
|
||||
console.log(`Initialising keybase with user "${username}" and key: "${'*'.repeat(paperkey.length)}"...`);
|
||||
await bot.init(username, paperkey, { verbose: false });
|
||||
|
||||
const channel = {
|
||||
name: 'nymtech_bot',
|
||||
membersType: 'team',
|
||||
topicName: keybaseChannel,
|
||||
topic_type: 'CHAT',
|
||||
};
|
||||
const message = {
|
||||
body: result,
|
||||
};
|
||||
|
||||
console.log(`Sending to ${channel.name}#${channel.topicName}...`);
|
||||
await bot.chat.send(channel, message);
|
||||
|
||||
console.log('Message sent!');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exitCode = -1;
|
||||
} finally {
|
||||
await bot.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,11 @@
|
||||
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View output:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
|
||||
> ✅ **SUCCESS**
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
|
||||
Commit message:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Publish Tauri Wallet
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- nym-wallet-*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Run a one-line script
|
||||
run: echo Hello, world!
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Generate TS types
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- "explorer/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "explorer/**"
|
||||
|
||||
jobs:
|
||||
nym-wallet-types:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
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 nym-wallet/src-tauri && cargo test
|
||||
- uses: EndBug/add-and-commit@v7.2.1 # https://github.com/marketplace/actions/add-commit
|
||||
with:
|
||||
add: '["nym-wallet"]'
|
||||
message: "[ci skip] Generate TS types"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,9 +1,12 @@
|
||||
name: Wasm Client
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'explorer/**'
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
wasm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -16,10 +19,16 @@ jobs:
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
# token credentials (non-coconut) don't work for wasm right now
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: build
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --features=coconut
|
||||
|
||||
# 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
|
||||
@@ -36,4 +45,4 @@ jobs:
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: clippy
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
|
||||
|
||||
@@ -11,7 +11,6 @@ target
|
||||
/.vscode/settings.json
|
||||
validator/.vscode
|
||||
sample-configs/validator-config.toml
|
||||
.vscode
|
||||
scripts/deploy_qa.sh
|
||||
scripts/run_gate.sh
|
||||
scripts/run_mix.sh
|
||||
@@ -26,3 +25,12 @@ v6-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
|
||||
contracts/mixnet/code_id
|
||||
contracts/mixnet/Justfile
|
||||
contracts/mixnet/Makefile
|
||||
validator-config
|
||||
*.patch
|
||||
@@ -1,10 +1,258 @@
|
||||
<!--
|
||||
Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
# Changelog
|
||||
|
||||
## [v0.11.0](https://github.com/nymtech/nym/tree/v0.11.0) (2021-07-21)
|
||||
|
||||
[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)
|
||||
@@ -17,6 +265,7 @@ This release brings networking improvements, eliminating blocking calls and impr
|
||||
|
||||
**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)
|
||||
@@ -269,7 +518,6 @@ This release introduces, among other things, the following improvements:
|
||||
- could not count to ten properly [\#262](https://github.com/nymtech/nym/pull/262) ([ststefa](https://github.com/ststefa))
|
||||
- build\(deps\): bump websocket-extensions from 0.1.3 to 0.1.4 in /clients/webassembly/js-example [\#261](https://github.com/nymtech/nym/pull/261) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
- add disabling feature 'offline-test' for network-dependent tests [\#260](https://github.com/nymtech/nym/pull/260) ([hyperfekt](https://github.com/hyperfekt))
|
||||
- Filtering compatible node versions [\#259](https://github.com/nymtech/nym/pull/259) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.7.0](https://github.com/nymtech/nym/tree/v0.7.0) (2020-06-08)
|
||||
|
||||
@@ -299,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)
|
||||
@@ -324,15 +572,16 @@ 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:**
|
||||
|
||||
- Filtering compatible node versions [\#259](https://github.com/nymtech/nym/pull/259) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- systemd service unit example [\#257](https://github.com/nymtech/nym/pull/257) ([ststefa](https://github.com/ststefa))
|
||||
- renaming desktop to native client [\#251](https://github.com/nymtech/nym/pull/251) ([futurechimp](https://github.com/futurechimp))
|
||||
- Adding a pipenv dependencies file to the python client example [\#250](https://github.com/nymtech/nym/pull/250) ([futurechimp](https://github.com/futurechimp))
|
||||
@@ -471,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:**
|
||||
|
||||
@@ -575,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:**
|
||||
|
||||
@@ -619,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))
|
||||
@@ -642,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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package.mixnet-contracts]
|
||||
opt-level = 3
|
||||
debug = false
|
||||
debug-assertions = false
|
||||
codegen-units = 1
|
||||
incremental = false
|
||||
overflow-checks = true
|
||||
|
||||
[profile.dev]
|
||||
@@ -19,20 +12,23 @@ 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/client-libs/validator-client-rest",
|
||||
"common/coconut-interface",
|
||||
"common/config",
|
||||
"common/credentials",
|
||||
"common/crypto",
|
||||
"common/erc20-bridge-contract",
|
||||
"common/mixnet-contract",
|
||||
"common/mixnode-common",
|
||||
"common/network-defaults",
|
||||
"common/nonexhaustive-delayqueue",
|
||||
"common/nymsphinx",
|
||||
"common/nymsphinx/acknowledgements",
|
||||
@@ -45,15 +41,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 = [
|
||||
@@ -63,7 +60,7 @@ default-members = [
|
||||
"gateway",
|
||||
"service-providers/network-requester",
|
||||
"mixnode",
|
||||
"network-monitor",
|
||||
"validator-api",
|
||||
]
|
||||
|
||||
exclude = ["explorer"]
|
||||
exclude = ["explorer", "contracts", "tokenomics-py"]
|
||||
|
||||
@@ -5,8 +5,6 @@ SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
## The Nym Privacy Platform
|
||||
|
||||
This repository contains the Nym mixnet.
|
||||
|
||||
The platform is composed of multiple Rust crates. Top-level executable binary crates include:
|
||||
|
||||
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
@@ -15,6 +13,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
||||
* 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)
|
||||
@@ -22,7 +21,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
||||
|
||||
### Building
|
||||
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs).
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/0.11.0/overview/index/).
|
||||
|
||||
### Developing
|
||||
|
||||
@@ -32,6 +31,46 @@ There's a `.env.sample-dev` file provided which you can rename to `.env` if you
|
||||
|
||||
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.
|
||||
|
||||
### Rewards
|
||||
|
||||
Node, node operator and delegator rewards are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf). Below is a TLDR of the variables and formulas involved in calculating the epoch rewards. Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
|Symbol|Definition|
|
||||
|---|---|
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R">|global share of rewards available, starts at 2% of the reward pool.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R_{i}">|node reward for mixnode `i`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\sigma_{i}">|ratio of total node stake (node bond + all delegations) to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}">|ratio of stake operator has plaged to their node to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}">|fraction of total effort undertaken by node `i`, set to `1/k` in testnet Milhon.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=k">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `active set` size, and set to 5000 in testnet Milhon.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\alpha">|Sybil attack resistance parameter - the higher this parameter is set the stronger the reduction in competitivness gets for a Sybil attacker.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}">|declared profit margin of operator `i`, defaults to 10% in testnet Milhon.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}">|cost of operating node `i` for the duration of the rewarding eopoch, set to 40 Nym for testnet Milhon.
|
||||
|
||||
Node reward for node `i` is determined as:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)">
|
||||
|
||||
where:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\sigma^'_{i} = min\{\sigma_{i}, 1/k\}">
|
||||
|
||||
and
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\lambda^'_{i} = min\{\lambda_{i}, 1/k\}">
|
||||
|
||||
Operator of node `i` is credited with the following amount:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}">
|
||||
|
||||
Delegate with stake `s` recieves:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}">
|
||||
|
||||
where `s'` is stake `s` scaled over total token circulating supply.
|
||||
|
||||
### 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.2"
|
||||
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" }
|
||||
@@ -25,7 +26,10 @@ nonexhaustive-delayqueue = { path = "../../common/nonexhaustive-delayqueue" }
|
||||
nymsphinx = { path = "../../common/nymsphinx" }
|
||||
pemstore = { path = "../../common/pemstore" }
|
||||
topology = { path = "../../common/topology" }
|
||||
validator-client-rest = { path = "../../common/client-libs/validator-client-rest" }
|
||||
validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[features]
|
||||
coconut = []
|
||||
@@ -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,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};
|
||||
@@ -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;
|
||||
@@ -51,7 +40,7 @@ impl MixTrafficController {
|
||||
async fn on_messages(&mut self, mut mix_packets: Vec<MixPacket>) {
|
||||
debug_assert!(!mix_packets.is_empty());
|
||||
|
||||
let success = if mix_packets.len() == 1 {
|
||||
let result = if mix_packets.len() == 1 {
|
||||
let mix_packet = mix_packets.pop().unwrap();
|
||||
self.gateway_client.send_mix_packet(mix_packet).await
|
||||
} else {
|
||||
@@ -60,7 +49,7 @@ impl MixTrafficController {
|
||||
.await
|
||||
};
|
||||
|
||||
match success {
|
||||
match result {
|
||||
Err(e) => {
|
||||
error!("Failed to send sphinx packet(s) to the gateway! - {:?}", e);
|
||||
self.consecutive_gateway_failure_count += 1;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
@@ -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,20 +50,9 @@ 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 {
|
||||
// at this point I'm not entirely sure how to deal with this warning without
|
||||
// some considerable refactoring
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
ack_key: Arc<AckKey>,
|
||||
ack_wait_multiplier: f64,
|
||||
@@ -84,8 +61,6 @@ 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,
|
||||
@@ -95,8 +70,6 @@ impl Config {
|
||||
average_message_sending_delay,
|
||||
average_packet_delay_duration,
|
||||
average_ack_delay_duration,
|
||||
packet_mode,
|
||||
vpn_key_reuse_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,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(
|
||||
@@ -174,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();
|
||||
|
||||
@@ -182,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
|
||||
});
|
||||
@@ -201,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.
|
||||
@@ -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,7 +130,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);
|
||||
|
||||
// check if we have anything immediately available
|
||||
if let Some(real_available) = self.received_buffer.pop_front() {
|
||||
@@ -190,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,
|
||||
@@ -260,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;
|
||||
@@ -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!(
|
||||
@@ -196,7 +185,7 @@ impl ReceivedMessagesBuffer {
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySurbEncryptionAlgorithm>();
|
||||
|
||||
let mut reply_msg = stream_cipher::decrypt::<ReplySurbEncryptionAlgorithm>(
|
||||
&reply_key.inner(),
|
||||
reply_key.inner(),
|
||||
&zero_iv,
|
||||
reply_ciphertext,
|
||||
);
|
||||
|
||||
@@ -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 log::*;
|
||||
use nymsphinx::anonymous_replies::{
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -23,6 +14,7 @@ use tokio::runtime::Handle;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
use tokio::task::JoinHandle;
|
||||
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
|
||||
}
|
||||
@@ -115,7 +107,7 @@ impl TopologyAccessor {
|
||||
self.inner.read().await.into()
|
||||
}
|
||||
|
||||
async fn update_global_topology(&mut self, new_topology: Option<NymTopology>) {
|
||||
async fn update_global_topology(&self, new_topology: Option<NymTopology>) {
|
||||
self.inner.write().await.update(new_topology);
|
||||
}
|
||||
|
||||
@@ -136,56 +128,128 @@ impl Default for TopologyAccessor {
|
||||
}
|
||||
|
||||
pub struct TopologyRefresherConfig {
|
||||
validator_rcp_base_url: String,
|
||||
mixnet_contract_address: String,
|
||||
validator_api_urls: Vec<Url>,
|
||||
refresh_rate: time::Duration,
|
||||
client_version: String,
|
||||
}
|
||||
|
||||
impl TopologyRefresherConfig {
|
||||
pub fn new(
|
||||
validator_rcp_base_url: String,
|
||||
mixnet_contract_address: String,
|
||||
validator_api_urls: Vec<Url>,
|
||||
refresh_rate: time::Duration,
|
||||
client_version: String,
|
||||
) -> Self {
|
||||
TopologyRefresherConfig {
|
||||
validator_rcp_base_url,
|
||||
mixnet_contract_address,
|
||||
validator_api_urls,
|
||||
refresh_rate,
|
||||
client_version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TopologyRefresher {
|
||||
validator_client: validator_client_rest::Client,
|
||||
validator_client: validator_client::ApiClient,
|
||||
client_version: String,
|
||||
|
||||
validator_api_urls: Vec<Url>,
|
||||
topology_accessor: TopologyAccessor,
|
||||
refresh_rate: Duration,
|
||||
|
||||
currently_used_api: usize,
|
||||
was_latest_valid: bool,
|
||||
}
|
||||
|
||||
impl TopologyRefresher {
|
||||
pub fn new(cfg: TopologyRefresherConfig, topology_accessor: TopologyAccessor) -> Self {
|
||||
let validator_client_config = validator_client_rest::Config::new(
|
||||
cfg.validator_rcp_base_url,
|
||||
cfg.mixnet_contract_address,
|
||||
);
|
||||
let validator_client = validator_client_rest::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()),
|
||||
client_version: cfg.client_version,
|
||||
validator_api_urls: cfg.validator_api_urls,
|
||||
topology_accessor,
|
||||
refresh_rate: cfg.refresh_rate,
|
||||
currently_used_api: 0,
|
||||
was_latest_valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
/// Verifies whether nodes a reasonably distributed among all mix layers.
|
||||
///
|
||||
/// In ideal world we would have 33% nodes on layer 1, 33% on layer 2 and 33% on layer 3.
|
||||
/// However, this is a rather unrealistic expectation, instead we check whether there exists
|
||||
/// a layer with more than 66% of nodes or with fewer than 15% and if so, we trigger a failure.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `topology`: active topology constructed from validator api data
|
||||
/// * `mixnodes_count`: total number of active mixnodes
|
||||
fn check_layer_distribution(
|
||||
&self,
|
||||
active_topology: &NymTopology,
|
||||
mixnodes_count: usize,
|
||||
) -> bool {
|
||||
let mixes = active_topology.mixes();
|
||||
if active_topology.gateways().is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trivial check to see if have at least a single node on each layer (regardless of active set size)
|
||||
if mixes.get(&1).is_none() || mixes.get(&2).is_none() || mixes.get(&3).is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let upper_bound = (mixnodes_count as f32 * 0.66) as usize;
|
||||
let lower_bound = (mixnodes_count as f32 * 0.15) as usize;
|
||||
|
||||
let layer1 = mixes.get(&1).unwrap().len();
|
||||
let layer2 = mixes.get(&2).unwrap().len();
|
||||
let layer3 = mixes.get(&3).unwrap().len();
|
||||
|
||||
if layer1 < lower_bound || layer1 > upper_bound {
|
||||
warn!(
|
||||
"nodes: {}, layer1: {}, layer2: {}, layer3: {}",
|
||||
mixnodes_count, layer1, layer2, layer3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if layer2 < lower_bound || layer2 > upper_bound {
|
||||
warn!(
|
||||
"nodes: {}, layer1: {}, layer2: {}, layer3: {}",
|
||||
mixnodes_count, layer1, layer2, layer3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if layer3 < lower_bound || layer3 > upper_bound {
|
||||
warn!(
|
||||
"nodes: {}, layer1: {}, layer2: {}, layer3: {}",
|
||||
mixnodes_count, layer1, layer2, layer3
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(&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_mix_nodes().await {
|
||||
let mixnodes = match self.validator_client.get_cached_active_mixnodes().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network mixnodes - {}", err);
|
||||
return None;
|
||||
@@ -193,7 +257,7 @@ impl TopologyRefresher {
|
||||
Ok(mixes) => mixes,
|
||||
};
|
||||
|
||||
let gateways = match self.validator_client.get_gateways().await {
|
||||
let gateways = match self.validator_client.get_cached_gateways().await {
|
||||
Err(err) => {
|
||||
error!("failed to get network gateways - {}", err);
|
||||
return None;
|
||||
@@ -201,17 +265,26 @@ impl TopologyRefresher {
|
||||
Ok(gateways) => gateways,
|
||||
};
|
||||
|
||||
let topology = nym_topology_from_bonds(mixnodes, gateways);
|
||||
let mixnodes_count = mixnodes.len();
|
||||
let topology =
|
||||
nym_topology_from_bonds(mixnodes, gateways).filter_system_version(&self.client_version);
|
||||
|
||||
// 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")))
|
||||
if !self.check_layer_distribution(&topology, mixnodes_count) {
|
||||
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used.");
|
||||
None
|
||||
} else {
|
||||
Some(topology)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -234,7 +307,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,35 +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";
|
||||
pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str =
|
||||
"TODO: THIS NEEDS TO BE FILLED WITH SOME REASONABLE VALUE!";
|
||||
|
||||
// 'DEBUG'
|
||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||
|
||||
@@ -37,59 +20,12 @@ 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)
|
||||
}
|
||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
pub fn missing_string_value() -> String {
|
||||
MISSING_VALUE.to_string()
|
||||
@@ -167,6 +103,17 @@ impl<T: NymConfig> Config<T> {
|
||||
self::Client::<T>::default_reply_encryption_key_store_path(&id);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
if self
|
||||
.client
|
||||
.backup_bandwidth_token_keys_dir
|
||||
.as_os_str()
|
||||
.is_empty()
|
||||
{
|
||||
self.client.backup_bandwidth_token_keys_dir =
|
||||
self::Client::<T>::default_backup_bandwidth_token_keys_dir(&id);
|
||||
}
|
||||
|
||||
self.client.id = id;
|
||||
}
|
||||
|
||||
@@ -178,12 +125,18 @@ 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();
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
pub fn with_eth_private_key<S: Into<String>>(&mut self, eth_private_key: S) {
|
||||
self.client.eth_private_key = eth_private_key.into();
|
||||
}
|
||||
|
||||
pub fn set_mixnet_contract<S: Into<String>>(&mut self, contract_address: S) {
|
||||
self.client.mixnet_contract_address = contract_address.into();
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
pub fn with_eth_endpoint<S: Into<String>>(&mut self, eth_endpoint: S) {
|
||||
self.client.eth_endpoint = eth_endpoint.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) {
|
||||
@@ -192,14 +145,6 @@ impl<T: NymConfig> Config<T> {
|
||||
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();
|
||||
}
|
||||
@@ -240,12 +185,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_mixnet_contract_address(&self) -> String {
|
||||
self.client.mixnet_contract_address.clone()
|
||||
pub fn get_validator_api_endpoints(&self) -> Vec<Url> {
|
||||
self.client.validator_api_urls.clone()
|
||||
}
|
||||
|
||||
pub fn get_gateway_id(&self) -> String {
|
||||
@@ -256,21 +197,28 @@ impl<T: NymConfig> Config<T> {
|
||||
self.client.gateway_listener.clone()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
pub fn get_backup_bandwidth_token_keys_dir(&self) -> PathBuf {
|
||||
self.client.backup_bandwidth_token_keys_dir.clone()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
pub fn get_eth_endpoint(&self) -> String {
|
||||
self.client.eth_endpoint.clone()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
pub fn get_eth_private_key(&self) -> String {
|
||||
self.client.eth_private_key.clone()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -286,11 +234,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 {
|
||||
@@ -305,21 +249,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(DEFAULT_VPN_KEY_REUSE_LIMIT),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_version(&self) -> &str {
|
||||
&self.client.version
|
||||
}
|
||||
@@ -344,19 +273,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,
|
||||
|
||||
/// Address of the validator contract managing the network.
|
||||
#[serde(default = "missing_string_value")]
|
||||
mixnet_contract_address: 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,6 +307,20 @@ pub struct Client<T> {
|
||||
/// Address of the gateway listener to which all client requests should be sent.
|
||||
gateway_listener: String,
|
||||
|
||||
/// Path to directory containing public/private keys used for bandwidth token purchase.
|
||||
/// Those are saved in case of emergency, to be able to reclaim bandwidth tokens.
|
||||
/// The public key is the name of the file, while the private key is the content.
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
backup_bandwidth_token_keys_dir: PathBuf,
|
||||
|
||||
/// Ethereum private key.
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
eth_private_key: String,
|
||||
|
||||
/// Address to an Ethereum full node.
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
eth_endpoint: String,
|
||||
|
||||
/// nym_home_directory specifies absolute path to the home nym Clients directory.
|
||||
/// It is expected to use default value and hence .toml file should not redefine this field.
|
||||
nym_root_directory: PathBuf,
|
||||
@@ -403,9 +335,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(),
|
||||
mixnet_contract_address: DEFAULT_MIXNET_CONTRACT_ADDRESS.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(),
|
||||
@@ -415,6 +345,12 @@ impl<T: NymConfig> Default for Client<T> {
|
||||
reply_encryption_key_store_path: Default::default(),
|
||||
gateway_id: "".to_string(),
|
||||
gateway_listener: "".to_string(),
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
backup_bandwidth_token_keys_dir: Default::default(),
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
eth_private_key: "".to_string(),
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
eth_endpoint: "".to_string(),
|
||||
nym_root_directory: T::default_root_directory(),
|
||||
super_struct: Default::default(),
|
||||
}
|
||||
@@ -423,44 +359,43 @@ 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")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
fn default_backup_bandwidth_token_keys_dir(id: &str) -> PathBuf {
|
||||
T::default_data_directory(Some(id)).join("backup_bandwidth_token_keys")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Logging {}
|
||||
|
||||
impl Default for Logging {
|
||||
fn default() -> Self {
|
||||
Logging {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Debug {
|
||||
@@ -468,20 +403,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
|
||||
@@ -492,58 +421,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 {
|
||||
@@ -558,7 +465,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,8 +1,9 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "0.9.2"
|
||||
version = "0.11.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.56"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -16,21 +17,23 @@ 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" }
|
||||
coconut-interface = { path = "../../common/coconut-interface", optional = true }
|
||||
credentials = { path = "../../common/credentials", optional = true }
|
||||
config = { path = "../../common/config" }
|
||||
crypto = { path = "../../common/crypto" }
|
||||
gateway-client = { path = "../../common/client-libs/gateway-client" }
|
||||
@@ -39,8 +42,11 @@ nymsphinx = { path = "../../common/nymsphinx" }
|
||||
pemstore = { path = "../../common/pemstore" }
|
||||
topology = { path = "../../common/topology" }
|
||||
websocket-requests = { path = "websocket-requests" }
|
||||
validator-client-rest = { path = "../../common/client-libs/validator-client-rest" }
|
||||
validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
version-checker = { path = "../../common/version-checker" }
|
||||
|
||||
[features]
|
||||
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut"]
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0" # for the "textsend" example
|
||||
serde_json = "1.0" # for the "textsend" example
|
||||
|
||||
@@ -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,16 +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 }}'
|
||||
|
||||
# Address of the validator contract managing the network.
|
||||
mixnet_contract_address = '{{ client.mixnet_contract_address }}
|
||||
|
||||
# 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 }}'
|
||||
@@ -57,6 +42,17 @@ public_encryption_key_file = '{{ client.public_encryption_key_file }}'
|
||||
# sent but not received back.
|
||||
reply_encryption_key_store_path = '{{ client.reply_encryption_key_store_path }}'
|
||||
|
||||
# Path to directory containing public/private keys used for bandwidth token purchase.
|
||||
# Those are saved in case of emergency, to be able to reclaim bandwidth tokens.
|
||||
# The public key is the name of the file, while the private key is the content.
|
||||
backup_bandwidth_token_keys_dir = '{{ client.backup_bandwidth_token_keys_dir }}'
|
||||
|
||||
# Ethereum private key.
|
||||
eth_private_key = '{{ client.eth_private_key }}'
|
||||
|
||||
# Addess to an Ethereum full node.
|
||||
eth_endpoint = '{{ client.eth_endpoint }}'
|
||||
|
||||
##### additional client config options #####
|
||||
|
||||
# ID of the gateway from which the client should be fetching messages.
|
||||
|
||||
@@ -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;
|
||||
@@ -43,10 +32,11 @@ use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use gateway_client::bandwidth::BandwidthController;
|
||||
|
||||
pub(crate) mod config;
|
||||
|
||||
pub struct NymClient {
|
||||
@@ -106,21 +96,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 +120,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 +128,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,44 +182,53 @@ 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 {
|
||||
#[cfg(feature = "coconut")]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
*self.key_manager.identity_keypair().public_key(),
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_eth_endpoint(),
|
||||
self.config.get_base().get_eth_private_key(),
|
||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||
)
|
||||
.expect("Could not create bandwidth controller");
|
||||
|
||||
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(),
|
||||
Some(bandwidth_controller),
|
||||
);
|
||||
|
||||
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_mixnet_contract_address(),
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
self.config.get_base().get_topology_refresh_rate(),
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
);
|
||||
let mut topology_refresher =
|
||||
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
|
||||
@@ -392,9 +381,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,18 +7,22 @@ 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::{filter::VersionFilterable, gateway};
|
||||
use url::Url;
|
||||
|
||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
App::new("init")
|
||||
let app = App::new("init")
|
||||
.about("Initialise a Nym client. Do this first!")
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
@@ -42,15 +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("mixnet-contract")
|
||||
.long("mixnet-contract")
|
||||
.help("Address of the validator contract managing the network")
|
||||
.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")
|
||||
@@ -62,31 +50,34 @@ 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`
|
||||
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
||||
)
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(Arg::with_name("eth_endpoint")
|
||||
.long("eth_endpoint")
|
||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true)
|
||||
.required(true))
|
||||
.arg(Arg::with_name("eth_private_key")
|
||||
.long("eth_private_key")
|
||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true)
|
||||
.required(true));
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -96,21 +87,21 @@ 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,
|
||||
mixnet_contract: &str,
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<&str>,
|
||||
) -> gateway::Node {
|
||||
let validator_client_config =
|
||||
validator_client_rest::Config::new(validator_server, mixnet_contract);
|
||||
let validator_client = validator_client_rest::Client::new(validator_client_config);
|
||||
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_gateways().await.unwrap();
|
||||
let gateways = validator_client.get_cached_gateways().await.unwrap();
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
@@ -135,12 +126,48 @@ async fn gateway_details(
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -168,8 +195,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_mixnet_contract_address(),
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
@@ -178,11 +204,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()
|
||||
@@ -202,5 +228,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,31 +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;
|
||||
|
||||
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);
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
if let Some(contract_address) = matches.value_of("mixnet-contract") {
|
||||
config.get_base_mut().set_mixnet_contract(contract_address)
|
||||
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
|
||||
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") {
|
||||
@@ -36,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
|
||||
@@ -48,5 +43,14 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi
|
||||
config = config.with_port(port.unwrap());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
if let Some(eth_endpoint) = matches.value_of("eth_endpoint") {
|
||||
config.get_base_mut().with_eth_endpoint(eth_endpoint);
|
||||
}
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
if let Some(eth_private_key) = matches.value_of("eth_private_key") {
|
||||
config.get_base_mut().with_eth_private_key(eth_private_key);
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -21,7 +10,7 @@ use log::*;
|
||||
use version_checker::is_minor_version_compatible;
|
||||
|
||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
App::new("run")
|
||||
let app = App::new("run")
|
||||
.about("Run the Nym client with provided configuration client optionally overriding set parameters")
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
@@ -30,15 +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("mixnet-contract")
|
||||
.long("mixnet-contract")
|
||||
.help("Address of the validator contract managing the network")
|
||||
.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")
|
||||
@@ -49,23 +33,24 @@ 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")
|
||||
.help("Port for the socket (if applicable) to listen on")
|
||||
.takes_value(true)
|
||||
)
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(Arg::with_name("eth_endpoint")
|
||||
.long("eth_endpoint")
|
||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("eth_private_key")
|
||||
.long("eth_private_key")
|
||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true));
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
// this only checks compatibility between config the binary. It does not take into consideration
|
||||
@@ -90,7 +75,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,24 +1,19 @@
|
||||
// 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!(
|
||||
@@ -41,199 +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,
|
||||
};
|
||||
|
||||
let from = match from.strip_prefix("V") {
|
||||
Some(stripped) => stripped,
|
||||
None => from,
|
||||
};
|
||||
|
||||
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 client from before v0.8.0 is not supported. Please run `init` with new binary instead");
|
||||
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");
|
||||
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
|
||||
} else {
|
||||
Version::new(0, 9, 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(&from_version, &to_version);
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
println!(
|
||||
"Setting validator REST endpoint to to {}",
|
||||
DEFAULT_VALIDATOR_REST_ENDPOINT
|
||||
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
|
||||
);
|
||||
|
||||
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);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(from_version, to_version);
|
||||
|
||||
config
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
fn patch_09x_upgrade(mut config: Config, _matches: &ArgMatches) -> Config {
|
||||
// this call must succeed as it was already called before
|
||||
let from_version = Version::parse(config.get_base().get_version()).unwrap();
|
||||
let to_version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
|
||||
print_start_upgrade(&from_version, &to_version);
|
||||
|
||||
// 0.9.1 upgrade:
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {:?}", err);
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(from_version, to_version);
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
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),
|
||||
)
|
||||
// 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 unsupported_upgrade(current_version: Version, config_version: Version) -> ! {
|
||||
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)
|
||||
}
|
||||
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches) {
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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, 12, 0)
|
||||
};
|
||||
|
||||
print_start_upgrade(&config_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());
|
||||
|
||||
config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {:?}", err);
|
||||
print_failed_upgrade(&config_version, &to_version);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(config_version, to_version);
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version) {
|
||||
loop {
|
||||
let config_version =
|
||||
Version::parse(config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse client version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
let config_version = parse_config_version(&config);
|
||||
|
||||
if config_version == current {
|
||||
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 => patch_09x_upgrade(config, &matches),
|
||||
_ => unsupported_upgrade(current, config_version),
|
||||
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(current, config_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);
|
||||
}
|
||||
|
||||
let config_version =
|
||||
Version::parse(existing_config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse client version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
if config_version.is_prerelease() || !config_version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade from non-released version {}. This is not supported!",
|
||||
config_version
|
||||
);
|
||||
process::exit(1)
|
||||
eprintln!("the existing configuration file does not seem to contain version number.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// here be upgrade path to 0.9.X and beyond based on version number from config
|
||||
if config_version == current {
|
||||
println!("You're using the most recent version!");
|
||||
} else {
|
||||
do_upgrade(existing_config, matches)
|
||||
}
|
||||
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},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
// 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;
|
||||
@@ -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());
|
||||
|
||||
@@ -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::error::ErrorKind;
|
||||
use crate::requests::ClientRequest;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "0.9.2"
|
||||
version = "0.11.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.56"
|
||||
|
||||
[lib]
|
||||
name = "nym_socks5"
|
||||
@@ -14,15 +15,18 @@ 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" }
|
||||
coconut-interface = { path = "../../common/coconut-interface", optional = true }
|
||||
credentials = { path = "../../common/credentials", optional = true }
|
||||
config = { path = "../../common/config" }
|
||||
crypto = { path = "../../common/crypto" }
|
||||
gateway-client = { path = "../../common/client-libs/gateway-client" }
|
||||
@@ -31,6 +35,10 @@ 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-rest = { path = "../../common/client-libs/validator-client-rest" }
|
||||
validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
version-checker = { path = "../../common/version-checker" }
|
||||
|
||||
[features]
|
||||
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut"]
|
||||
|
||||
@@ -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,16 +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 }}'
|
||||
|
||||
# Address of the validator contract managing the network.
|
||||
mixnet_contract_address = '{{ client.mixnet_contract_address }}
|
||||
|
||||
# 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 }}'
|
||||
@@ -57,6 +42,17 @@ public_encryption_key_file = '{{ client.public_encryption_key_file }}'
|
||||
# sent but not received back.
|
||||
reply_encryption_key_store_path = '{{ client.reply_encryption_key_store_path }}'
|
||||
|
||||
# Path to directory containing public/private keys used for bandwidth token purchase.
|
||||
# Those are saved in case of emergency, to be able to reclaim bandwidth tokens.
|
||||
# The public key is the name of the file, while the private key is the content.
|
||||
backup_bandwidth_token_keys_dir = '{{ client.backup_bandwidth_token_keys_dir }}'
|
||||
|
||||
# Ethereum private key.
|
||||
eth_private_key = '{{ client.eth_private_key }}'
|
||||
|
||||
# Addess to an Ethereum full node.
|
||||
eth_endpoint = '{{ client.eth_endpoint }}'
|
||||
|
||||
##### additional client config options #####
|
||||
|
||||
# ID of the gateway from which the client should be fetching messages.
|
||||
|
||||
@@ -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,9 +32,10 @@ use gateway_client::{
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use gateway_client::bandwidth::BandwidthController;
|
||||
|
||||
pub(crate) mod config;
|
||||
|
||||
pub struct NymClient {
|
||||
@@ -94,21 +84,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 +108,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 +116,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,44 +170,53 @@ 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 {
|
||||
#[cfg(feature = "coconut")]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
*self.key_manager.identity_keypair().public_key(),
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let bandwidth_controller = BandwidthController::new(
|
||||
self.config.get_base().get_eth_endpoint(),
|
||||
self.config.get_base().get_eth_private_key(),
|
||||
self.config.get_base().get_backup_bandwidth_token_keys_dir(),
|
||||
)
|
||||
.expect("Could not create bandwidth controller");
|
||||
|
||||
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(),
|
||||
Some(bandwidth_controller),
|
||||
);
|
||||
|
||||
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_mixnet_contract_address(),
|
||||
self.config.get_base().get_validator_api_endpoints(),
|
||||
self.config.get_base().get_topology_refresh_rate(),
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
);
|
||||
let mut topology_refresher =
|
||||
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
|
||||
@@ -342,9 +331,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,17 +7,20 @@ 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::{filter::VersionFilterable, gateway};
|
||||
use url::Url;
|
||||
|
||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
App::new("init")
|
||||
let app = App::new("init")
|
||||
.about("Initialise a Nym client. Do this first!")
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
@@ -47,15 +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("mixnet-contract")
|
||||
.long("mixnet-contract")
|
||||
.help("Address of the validator contract managing the network")
|
||||
.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")
|
||||
@@ -63,31 +50,34 @@ 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`
|
||||
.help("Mostly debug-related option to increase default traffic rate so that you would not need to modify config post init")
|
||||
)
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(Arg::with_name("eth_endpoint")
|
||||
.long("eth_endpoint")
|
||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true)
|
||||
.required(true))
|
||||
.arg(Arg::with_name("eth_private_key")
|
||||
.long("eth_private_key")
|
||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true)
|
||||
.required(true));
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -97,21 +87,21 @@ 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,
|
||||
mixnet_contract: &str,
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<&str>,
|
||||
) -> gateway::Node {
|
||||
let validator_client_config =
|
||||
validator_client_rest::Config::new(validator_server, mixnet_contract);
|
||||
let validator_client = validator_client_rest::Client::new(validator_client_config);
|
||||
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_gateways().await.unwrap();
|
||||
let gateways = validator_client.get_cached_gateways().await.unwrap();
|
||||
let valid_gateways = gateways
|
||||
.into_iter()
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
@@ -136,13 +126,49 @@ async fn gateway_details(
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -170,8 +196,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_mixnet_contract_address(),
|
||||
config.get_base().get_validator_api_endpoints(),
|
||||
chosen_gateway_id,
|
||||
)
|
||||
.await;
|
||||
@@ -180,11 +205,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()
|
||||
@@ -204,5 +229,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,41 +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;
|
||||
|
||||
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);
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
if let Some(contract_address) = matches.value_of("mixnet-contract") {
|
||||
config.get_base_mut().set_mixnet_contract(contract_address)
|
||||
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
|
||||
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
|
||||
@@ -44,5 +39,14 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi
|
||||
config = config.with_port(port.unwrap());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
if let Some(eth_endpoint) = matches.value_of("eth_endpoint") {
|
||||
config.get_base_mut().with_eth_endpoint(eth_endpoint);
|
||||
}
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
if let Some(eth_private_key) = matches.value_of("eth_private_key") {
|
||||
config.get_base_mut().with_eth_private_key(eth_private_key);
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -21,7 +10,7 @@ use log::*;
|
||||
use version_checker::is_minor_version_compatible;
|
||||
|
||||
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
|
||||
App::new("run")
|
||||
let app = App::new("run")
|
||||
.about("Run the Nym client with provided configuration client optionally overriding set parameters")
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
@@ -40,38 +29,34 @@ 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("mixnet-contract")
|
||||
.long("mixnet-contract")
|
||||
.help("Address of the validator contract managing the network")
|
||||
.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")
|
||||
.help("Port for the socket to listen on")
|
||||
.takes_value(true)
|
||||
)
|
||||
);
|
||||
#[cfg(not(feature = "coconut"))]
|
||||
let app = app
|
||||
.arg(Arg::with_name("eth_endpoint")
|
||||
.long("eth_endpoint")
|
||||
.help("URL of an Ethereum full node that we want to use for getting bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("eth_private_key")
|
||||
.long("eth_private_key")
|
||||
.help("Ethereum private key used for obtaining bandwidth tokens from ERC20 tokens")
|
||||
.takes_value(true));
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
// this only checks compatibility between config the binary. It does not take into consideration
|
||||
@@ -96,7 +81,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,24 +1,19 @@
|
||||
// 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!(
|
||||
@@ -41,199 +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,
|
||||
};
|
||||
|
||||
let from = match from.strip_prefix("V") {
|
||||
Some(stripped) => stripped,
|
||||
None => from,
|
||||
};
|
||||
|
||||
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 client from before v0.8.0 is not supported. Please run `init` with new binary instead");
|
||||
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");
|
||||
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
|
||||
} else {
|
||||
Version::new(0, 9, 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(&from_version, &to_version);
|
||||
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
println!(
|
||||
"Setting validator REST endpoint to {}",
|
||||
DEFAULT_VALIDATOR_REST_ENDPOINT
|
||||
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
|
||||
);
|
||||
|
||||
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);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(from_version, to_version);
|
||||
|
||||
config
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
fn patch_09x_upgrade(mut config: Config, _matches: &ArgMatches) -> Config {
|
||||
// this call must succeed as it was already called before
|
||||
let from_version = Version::parse(config.get_base().get_version()).unwrap();
|
||||
let to_version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
|
||||
print_start_upgrade(&from_version, &to_version);
|
||||
|
||||
// 0.9.1 upgrade:
|
||||
config
|
||||
.get_base_mut()
|
||||
.set_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {:?}", err);
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(from_version, to_version);
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
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-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 unsupported_upgrade(current_version: Version, config_version: Version) -> ! {
|
||||
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)
|
||||
}
|
||||
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches) {
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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, 12, 0)
|
||||
};
|
||||
|
||||
print_start_upgrade(&config_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());
|
||||
|
||||
config.save_to_file(None).unwrap_or_else(|err| {
|
||||
eprintln!("failed to overwrite config file! - {:?}", err);
|
||||
print_failed_upgrade(&config_version, &to_version);
|
||||
process::exit(1);
|
||||
});
|
||||
|
||||
print_successful_upgrade(config_version, to_version);
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version) {
|
||||
loop {
|
||||
let config_version =
|
||||
Version::parse(config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse client version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
let config_version = parse_config_version(&config);
|
||||
|
||||
if config_version == current {
|
||||
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 => patch_09x_upgrade(config, &matches),
|
||||
_ => unsupported_upgrade(current, config_version),
|
||||
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(current, config_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);
|
||||
}
|
||||
|
||||
let config_version =
|
||||
Version::parse(existing_config.get_base().get_version()).unwrap_or_else(|err| {
|
||||
eprintln!("failed to parse client version! - {:?}", err);
|
||||
process::exit(1)
|
||||
});
|
||||
|
||||
if config_version.is_prerelease() || !config_version.build.is_empty() {
|
||||
eprintln!(
|
||||
"Trying to upgrade from non-released version {}. This is not supported!",
|
||||
config_version
|
||||
);
|
||||
process::exit(1)
|
||||
eprintln!("the existing configuration file does not seem to contain version number.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// here be upgrade path to 0.9.X and beyond based on version number from config
|
||||
if config_version == current {
|
||||
println!("You're using the most recent version!");
|
||||
} else {
|
||||
do_upgrade(existing_config, matches)
|
||||
}
|
||||
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};
|
||||
|
||||
|
||||
@@ -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,
|
||||
@@ -190,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(())
|
||||
}
|
||||
|
||||
@@ -210,7 +211,7 @@ 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 {
|
||||
@@ -390,7 +391,7 @@ impl SocksClient {
|
||||
self.stream.write_all(&response).await?;
|
||||
|
||||
// Shutdown
|
||||
self.shutdown()?;
|
||||
self.shutdown().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -404,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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |