├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── auto_merge_prs.yml │ ├── bump_version.yml │ ├── commitlint.yml │ ├── github_release.yml │ ├── main.yml │ ├── pr.yml │ ├── security_audit.yml │ └── tag_release.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-BSD ├── LICENSE-MIT ├── README.md ├── codeowners └── src ├── cmd.rs ├── lib.rs └── main.rs /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thank you for contributing to the project! 11 | We recommend you check out our ["Contributing to the SAFE Network"](https://github.com/maidsafe/QA/blob/master/CONTRIBUTING.md) guide if you haven't already. 12 | 13 | **Describe the bug** 14 | A clear and concise description of what the bug is. 15 | 16 | **To Reproduce** 17 | Steps to reproduce the behavior, e.g.: 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Screenshots** 27 | If applicable, add screenshots to help explain your problem. 28 | 29 | **Desktop (please complete the following information where applicable):** 30 | - OS: [e.g. Ubuntu 18.04] 31 | - Shell: [e.g. Zsh] 32 | - Rust: [e.g. 1.42.0 stable] 33 | - Browser [e.g. chrome, safari] 34 | - Version [e.g. 22] 35 | - etc 36 | 37 | **Smartphone (please complete the following information where applicable):** 38 | - Device: [e.g. iPhone6] 39 | - OS: [e.g. iOS8.1] 40 | - Browser [e.g. stock browser, safari] 41 | - Version [e.g. 22] 42 | - etc 43 | 44 | **Additional context** 45 | Add any other context about the problem here. 46 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thank you for contributing to the project! 11 | We recommend you check out our ["Contributing to the SAFE Network"](https://github.com/maidsafe/QA/blob/master/CONTRIBUTING.md) guide if you haven't already. 12 | 13 | **Is your feature request related to a problem? Please describe.** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the solution you'd like** 17 | A clear and concise description of what you want to happen. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/workflows/auto_merge_prs.yml: -------------------------------------------------------------------------------- 1 | # auto merge workflow. 2 | # 3 | # Auto merge PR if commit msg begins with `chore(release):`, 4 | # or if it has been raised by Dependabot. 5 | # Uses https://github.com/ridedott/merge-me-action. 6 | 7 | name: Merge Version Change and Dependabot PRs automatically 8 | 9 | on: pull_request 10 | 11 | jobs: 12 | merge: 13 | runs-on: ubuntu-20.04 14 | steps: 15 | - uses: actions/checkout@v2 16 | with: 17 | fetch-depth: '0' 18 | 19 | - name: get commit message 20 | run: | 21 | commitmsg=$(git log --format=%s -n 1 ${{ github.event.pull_request.head.sha }}) 22 | echo "commitmsg=${commitmsg}" >> $GITHUB_ENV 23 | 24 | - name: show commit message 25 | run : echo $commitmsg 26 | 27 | - name: Merge Version change PR 28 | if: startsWith( env.commitmsg, 'chore(release):') 29 | uses: ridedott/merge-me-action@81667e6ae186ddbe6d3c3186d27d91afa7475e2c 30 | with: 31 | GITHUB_LOGIN: dirvine 32 | GITHUB_TOKEN: ${{ secrets.MERGE_BUMP_BRANCH_TOKEN }} 33 | MERGE_METHOD: REBASE 34 | 35 | - name: Dependabot Merge 36 | uses: ridedott/merge-me-action@master 37 | with: 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | MERGE_METHOD: REBASE 40 | -------------------------------------------------------------------------------- /.github/workflows/bump_version.yml: -------------------------------------------------------------------------------- 1 | name: Version bump and create PR for changes 2 | 3 | on: 4 | # Trigger the workflow on push only for the main branch 5 | push: 6 | branches: 7 | - main 8 | 9 | env: 10 | NODE_ENV: 'development' 11 | 12 | jobs: 13 | update_changelog: 14 | runs-on: ubuntu-20.04 15 | # Dont run if we're on a release commit 16 | if: "!startsWith(github.event.head_commit.message, 'chore(release):')" 17 | steps: 18 | - uses: actions/checkout@v2 19 | with: 20 | fetch-depth: '0' 21 | - name: Bump Version 22 | uses: maidsafe/rust-version-bump-branch-creator@v3 23 | with: 24 | token: ${{ secrets.BRANCH_CREATOR_TOKEN }} 25 | target_branch: main 26 | -------------------------------------------------------------------------------- /.github/workflows/commitlint.yml: -------------------------------------------------------------------------------- 1 | name: Commitlint 2 | on: [pull_request] 3 | 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-latest 7 | env: 8 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 9 | steps: 10 | - uses: actions/checkout@v2 11 | with: 12 | fetch-depth: 0 13 | - uses: wagoid/commitlint-github-action@f114310111fdbd07e99f47f9ca13d62b3ec98372 14 | -------------------------------------------------------------------------------- /.github/workflows/github_release.yml: -------------------------------------------------------------------------------- 1 | name: Create GitHub Release 2 | 3 | 4 | on: 5 | push: 6 | tags: 7 | - 'v*' 8 | 9 | jobs: 10 | release: 11 | # only if we have a tag 12 | name: Release 13 | runs-on: ubuntu-20.04 14 | if: "startsWith(github.event.head_commit.message, 'chore(release):')" 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | fetch-depth: '0' 20 | 21 | - name: Set tag as env 22 | shell: bash 23 | run: echo "RELEASE_VERSION=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV 24 | 25 | - name: lets check tag 26 | shell: bash 27 | run: echo ${{ env.RELEASE_VERSION }} 28 | 29 | - name: Generate Changelog 30 | shell: bash 31 | run: awk '/# \[/{c++;p=1}{if(c==2){exit}}p;' CHANGELOG.md > RELEASE-CHANGELOG.txt 32 | - run: cat RELEASE-CHANGELOG.txt 33 | - name: Release generation 34 | uses: softprops/action-gh-release@91409e712cf565ce9eff10c87a8d1b11b81757ae 35 | env: 36 | GITHUB_TOKEN: ${{ secrets.MERGE_BUMP_BRANCH_TOKEN }} 37 | with: 38 | body_path: RELEASE-CHANGELOG.txt 39 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # Push to main workflow. 2 | # 3 | # Runs when a PR has been merged to the main branch. 4 | # 5 | # 1. Generates a release build. 6 | # 2. If the last commit is a version change, publish. 7 | 8 | name: Main 9 | 10 | on: 11 | push: 12 | branches: 13 | - main 14 | 15 | env: 16 | # Run all cargo commands with --verbose. 17 | CARGO_TERM_VERBOSE: true 18 | RUST_BACKTRACE: 1 19 | 20 | jobs: 21 | build: 22 | name: Build 23 | runs-on: ${{ matrix.os }} 24 | strategy: 25 | matrix: 26 | os: [ubuntu-latest, windows-latest, macOS-latest] 27 | steps: 28 | - uses: actions/checkout@v2 29 | 30 | - name: Install Rust 31 | uses: actions-rs/toolchain@v1 32 | with: 33 | profile: minimal 34 | toolchain: stable 35 | override: true 36 | 37 | # Cache. 38 | - name: Cargo cache registry, index and build 39 | uses: actions/cache@v2.1.4 40 | with: 41 | path: | 42 | ~/.cargo/registry 43 | ~/.cargo/git 44 | target 45 | key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} 46 | 47 | # Make sure the code builds. 48 | - name: Run cargo build 49 | run: cargo build --release --workspace 50 | 51 | # Publish if we're on a release commit 52 | publish: 53 | name: Publish 54 | runs-on: ubuntu-latest 55 | needs: build 56 | if: "startsWith(github.event.head_commit.message, 'chore(release):')" 57 | steps: 58 | - uses: actions/checkout@v2 59 | # checkout with fetch-depth: '0' to be sure to retrieve all commits to look for the semver commit message 60 | with: 61 | fetch-depth: '0' 62 | 63 | # Install Rust 64 | - uses: actions-rs/toolchain@v1 65 | with: 66 | profile: minimal 67 | toolchain: stable 68 | override: true 69 | 70 | # Publish to crates.io. 71 | - name: Cargo Login 72 | run: cargo login ${{ secrets.CRATES_IO_TOKEN }} 73 | 74 | - name: Cargo Publish 75 | run: cargo publish --allow-dirty 76 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | # PR workflow. 2 | # 3 | # Runs full suite of checks, with warnings treated as errors. 4 | # Gather code coverage stats and publish them on coveralls.io. 5 | 6 | name: PR 7 | 8 | on: pull_request 9 | 10 | env: 11 | # Run all cargo commands with --verbose. 12 | CARGO_TERM_VERBOSE: true 13 | RUST_BACKTRACE: 1 14 | # Deny all compiler warnings. 15 | RUSTFLAGS: "-D warnings" 16 | 17 | jobs: 18 | checks: 19 | if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" 20 | name: fmt & clippy 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - name: Install Rust and required components 26 | uses: actions-rs/toolchain@v1 27 | with: 28 | profile: minimal 29 | toolchain: stable 30 | override: true 31 | components: rustfmt, clippy 32 | 33 | # Cache. 34 | - name: Cargo cache registry, index and build 35 | uses: actions/cache@v2.1.4 36 | with: 37 | path: | 38 | ~/.cargo/registry 39 | ~/.cargo/git 40 | target 41 | key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} 42 | 43 | # Check if the code is formatted correctly. 44 | - name: Check formatting 45 | run: cargo fmt --all -- --check 46 | 47 | # Run Clippy. 48 | - name: Clippy checks 49 | run: cargo clippy --all-targets --all-features 50 | 51 | coverage: 52 | if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" 53 | name: Code coverage check 54 | runs-on: ubuntu-latest 55 | steps: 56 | - uses: actions/checkout@v2 57 | 58 | # Install Rust 59 | - uses: actions-rs/toolchain@v1 60 | with: 61 | profile: minimal 62 | toolchain: stable 63 | override: true 64 | 65 | # Cache. 66 | - name: Cargo cache registry, index and build 67 | uses: actions/cache@v2.1.4 68 | with: 69 | path: | 70 | ~/.cargo/registry 71 | ~/.cargo/git 72 | target 73 | key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} 74 | 75 | # Run cargo tarpaulin & push result to coveralls.io 76 | - name: rust-tarpaulin code coverage check 77 | uses: actions-rs/tarpaulin@v0.1 78 | with: 79 | args: '-v --release --out Lcov' 80 | - name: Push code coverage results to coveralls.io 81 | uses: coverallsapp/github-action@master 82 | with: 83 | github-token: ${{ secrets.GITHUB_TOKEN }} 84 | parallel: true 85 | path-to-lcov: ./lcov.info 86 | - name: Coveralls Finished 87 | uses: coverallsapp/github-action@master 88 | with: 89 | github-token: ${{ secrets.GITHUB_TOKEN }} 90 | parallel-finished: true 91 | 92 | build: 93 | if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" 94 | name: Build 95 | runs-on: ${{ matrix.os }} 96 | strategy: 97 | matrix: 98 | os: [ubuntu-latest, windows-latest, macOS-latest] 99 | steps: 100 | - uses: actions/checkout@v2 101 | - name: Install Rust 102 | uses: actions-rs/toolchain@v1 103 | with: 104 | profile: minimal 105 | toolchain: stable 106 | override: true 107 | 108 | # Cache. 109 | - name: Cargo cache registry, index and build 110 | uses: actions/cache@v2.1.4 111 | with: 112 | path: | 113 | ~/.cargo/registry 114 | ~/.cargo/git 115 | target 116 | key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} 117 | 118 | # Make sure the code builds. 119 | - name: Run cargo build 120 | run: cargo build --release 121 | 122 | cargo-udeps: 123 | if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" 124 | name: Unused dependency check 125 | runs-on: ubuntu-latest 126 | steps: 127 | - uses: actions/checkout@v2 128 | # Install Rust and required components 129 | - uses: actions-rs/toolchain@v1 130 | with: 131 | toolchain: nightly 132 | override: true 133 | 134 | - name: Run cargo-udeps 135 | uses: aig787/cargo-udeps-action@v1 136 | with: 137 | version: 'latest' 138 | args: '--all-targets' 139 | 140 | cargo-deny: 141 | if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" 142 | runs-on: ubuntu-latest 143 | steps: 144 | - uses: actions/checkout@v2 145 | 146 | # wget the shared deny.toml file from the QA repo 147 | - shell: bash 148 | run: wget https://raw.githubusercontent.com/maidsafe/QA/master/misc-scripts/deny.toml 149 | 150 | - uses: EmbarkStudios/cargo-deny-action@v1 151 | 152 | # Test publish using --dry-run. 153 | test-publish: 154 | if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" 155 | name: Test Publish 156 | runs-on: ubuntu-latest 157 | steps: 158 | - uses: actions/checkout@v2 159 | 160 | - name: Install Rust 161 | uses: actions-rs/toolchain@v1 162 | with: 163 | profile: minimal 164 | toolchain: stable 165 | override: true 166 | 167 | - name: Test publish 168 | run: cargo publish --dry-run --allow-dirty 169 | -------------------------------------------------------------------------------- /.github/workflows/security_audit.yml: -------------------------------------------------------------------------------- 1 | name: Security audit 2 | on: 3 | schedule: 4 | - cron: '0 0 * * *' 5 | jobs: 6 | audit: 7 | if: github.repository_owner == 'maidsafe' 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions-rs/audit-check@v1 12 | with: 13 | token: ${{ secrets.GITHUB_TOKEN }} 14 | -------------------------------------------------------------------------------- /.github/workflows/tag_release.yml: -------------------------------------------------------------------------------- 1 | name: Tag release commit 2 | 3 | on: 4 | # Trigger the workflow on push only for the main branch 5 | push: 6 | branches: 7 | - main 8 | 9 | env: 10 | NODE_ENV: 'development' 11 | GITHUB_TOKEN: ${{ secrets.BRANCH_CREATOR_TOKEN }} 12 | 13 | jobs: 14 | tag: 15 | runs-on: ubuntu-latest 16 | # Only run on a release commit 17 | if: "startsWith(github.event.head_commit.message, 'chore(release):')" 18 | steps: 19 | - uses: actions/checkout@v2 20 | with: 21 | fetch-depth: '0' 22 | token: ${{ secrets.BRANCH_CREATOR_TOKEN }} 23 | - run: echo "RELEASE_VERSION=$(git log -1 --pretty=%s)" >> $GITHUB_ENV 24 | # parse out non-tag text 25 | - run: echo "RELEASE_VERSION=$( echo $RELEASE_VERSION | sed 's/chore(release)://' )" >> $GITHUB_ENV 26 | # remove spaces, but add back in `v` to tag, which is needed for standard-version 27 | - run: echo "RELEASE_VERSION=v$(echo $RELEASE_VERSION | tr -d '[:space:]')" >> $GITHUB_ENV 28 | - run: echo $RELEASE_VERSION 29 | - run: git tag $RELEASE_VERSION 30 | 31 | - name: push version bump commit and tags 32 | uses: ad-m/github-push-action@master 33 | with: 34 | branch: main 35 | tags: true 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Executables 2 | *.exe 3 | *.out 4 | 5 | # Libraries and Objects 6 | *.o 7 | *.a 8 | *.so 9 | *.lo 10 | *.lib 11 | *.dll 12 | *.rlib 13 | *.dylib 14 | 15 | # Generated by Cargo 16 | bin/ 17 | tags* 18 | build/ 19 | target*/ 20 | build-tests/ 21 | 22 | # Generated by Editors 23 | *~ 24 | ~* 25 | *.bk 26 | /.idea 27 | *.swp 28 | *.sublime-* 29 | 30 | # Manual 31 | .cargo/ 32 | 33 | # Misc 34 | packages/ 35 | artifacts/ 36 | deploy/ 37 | .DS_Store 38 | *.bootstrap.cache 39 | cargo-all.sh 40 | bindings 41 | tmp 42 | *.orig 43 | 44 | 45 | #Added by cargo 46 | 47 | /target 48 | 49 | #Generated by the tool 50 | /nodes 51 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.13.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.13.0...v0.13.1) (2023-02-20) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * pass address to genesis node ([616d1a9](https://github.com/maidsafe/sn_launch_tool/commit/616d1a9a446eed64852e48954f37379e462fe5b5)) 11 | 12 | ## [0.13.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.12.2...v0.13.0) (2023-02-14) 13 | 14 | 15 | ### ⚠ BREAKING CHANGES 16 | 17 | * small change to force a new release 18 | 19 | * update copyright year ([0166910](https://github.com/maidsafe/sn_launch_tool/commit/01669104723ea8a3f8dd2c294deac2db056b9b28)) 20 | 21 | ### [0.12.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.12.1...v0.12.2) (2023-02-14) 22 | 23 | ### [0.12.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.12.1...v0.12.2) (2023-02-09) 24 | 25 | ### [0.12.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.12.1...v0.12.2) (2023-02-07) 26 | 27 | ### [0.12.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.12.0...v0.12.1) (2022-11-08) 28 | 29 | ## [0.12.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.11.1...v0.12.0) (2022-08-16) 30 | 31 | 32 | ### ⚠ BREAKING CHANGES 33 | 34 | * change target path where to copy network contacts file for clients to ~/.safe/network_contacts 35 | 36 | * change target path where to copy network contacts file for clients to ~/.safe/network_contacts ([45fd3d8](https://github.com/maidsafe/sn_launch_tool/commit/45fd3d81e6a41cda6116b2aaa8bbbdbf9f510319)) 37 | 38 | ### [0.11.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.11.0...v0.11.1) (2022-08-09) 39 | 40 | 41 | ### Bug Fixes 42 | 43 | * use a specific argument to set the network contacts file path for join API ([97f24af](https://github.com/maidsafe/sn_launch_tool/commit/97f24af009aaf1a899e7c707d637806aefa40a93)) 44 | 45 | ## [0.11.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.10.1...v0.11.0) (2022-08-08) 46 | 47 | 48 | ### ⚠ BREAKING CHANGES 49 | 50 | * set the --network-contacts-file node argument to the genesis node's prefix_map path 51 | 52 | ### Features 53 | 54 | * set the --network-contacts-file node argument to the genesis node's prefix_map path ([aa2ede9](https://github.com/maidsafe/sn_launch_tool/commit/aa2ede9b8b6088ba6401871b9596d6df2fb74062)) 55 | * set the genesis node as the default contact for local clients to bootstrap to ([77e0074](https://github.com/maidsafe/sn_launch_tool/commit/77e00745b87f0ef6eaadab843863fdbe8e922356)) 56 | 57 | ### [0.10.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.10.0...v0.10.1) (2022-07-11) 58 | 59 | ## [0.10.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.9...v0.10.0) (2022-07-06) 60 | 61 | 62 | ### ⚠ BREAKING CHANGES 63 | 64 | * **deps:** 65 | 66 | * **deps:** replace StructOpt with Clap ([34a6c7c](https://github.com/maidsafe/sn_launch_tool/commit/34a6c7c7b14636a85aed20095ea2590df273b3a5)) 67 | 68 | ### [0.9.9](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.8...v0.9.9) (2022-06-30) 69 | 70 | ### [0.9.8](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.7...v0.9.8) (2022-03-05) 71 | 72 | ### [0.9.7](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.6...v0.9.7) (2022-02-23) 73 | 74 | ### [0.9.6](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.5...v0.9.6) (2022-02-23) 75 | 76 | ### [0.9.5](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.4...v0.9.5) (2022-02-04) 77 | 78 | 79 | ### Features 80 | 81 | * enable flamegraph generation ([390fbe4](https://github.com/maidsafe/sn_launch_tool/commit/390fbe434e30dc4f4e5d1730e32284bb1dadfcd5)) 82 | 83 | ### [0.9.4](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.3...v0.9.4) (2021-11-29) 84 | 85 | 86 | ### Features 87 | 88 | * introduce skip auto port forwarding flag ([e52b711](https://github.com/maidsafe/sn_launch_tool/commit/e52b71138eb7dd9a76e938094ae0c231b245e047)) 89 | 90 | ### [0.9.3](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.2...v0.9.3) (2021-11-15) 91 | 92 | ### [0.9.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.1...v0.9.2) (2021-11-04) 93 | 94 | 95 | ### Features 96 | 97 | * provide a `--local` flag for joining network ([d48edfc](https://github.com/maidsafe/sn_launch_tool/commit/d48edfc138554905279480acca03d9fc309a26ce)) 98 | 99 | ### [0.9.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.9.0...v0.9.1) (2021-11-04) 100 | 101 | 102 | ### Features 103 | 104 | * add a flag to enable JSON logs on `sn_node` ([024d1e3](https://github.com/maidsafe/sn_launch_tool/commit/024d1e385b39227ad6a4fea8ee7552dca878caca)) 105 | 106 | ## [0.9.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.8.1...v0.9.0) (2021-10-27) 107 | 108 | 109 | ### ⚠ BREAKING CHANGES 110 | 111 | * The default value for `--keep-alive-interval-msec` if 112 | unspecified has changed to `None`, which will not pass any flag to 113 | `sn_node`, meaning the upstream default will apply. 114 | 115 | * don't specify keep-alive-interval by default ([aad3826](https://github.com/maidsafe/sn_launch_tool/commit/aad3826459da234e43199c90f90edeabdcb04e59)) 116 | 117 | ### [0.8.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.8.0...v0.8.1) (2021-10-26) 118 | 119 | ## [0.8.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.7.0...v0.8.0) (2021-09-22) 120 | 121 | 122 | ### ⚠ BREAKING CHANGES 123 | 124 | * launch args interval is now in millis, and default is 100 125 | 126 | ### Features 127 | 128 | * use millis for interval ([6763063](https://github.com/maidsafe/sn_launch_tool/commit/6763063100b1bde7f75e6b8f4818d46ecb9de4e2)) 129 | 130 | ## [0.7.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.6.0...v0.7.0) (2021-09-09) 131 | 132 | 133 | ### ⚠ BREAKING CHANGES 134 | 135 | * For genesis nodes, `sn_node` will now be invoked with 136 | `--first` without a value, which is not compatible with older versions 137 | of `sn_node`. 138 | 139 | * Update for changes to `sn_node` CLI ([b7d35f6](https://github.com/maidsafe/sn_launch_tool/commit/b7d35f648effe9fe6272b747e4e267c9b0b8423f)) 140 | 141 | ## [0.6.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.5.0...v0.6.0) (2021-09-09) 142 | 143 | 144 | ### ⚠ BREAKING CHANGES 145 | 146 | * this now expects the contacts info file to contain both the peer addreses and genesis key in hex format. 147 | 148 | ### Features 149 | 150 | * read genesis key from contacts info file and pass it as arg to joining nodes ([ffa48b3](https://github.com/maidsafe/sn_launch_tool/commit/ffa48b30cf734144398640b3be29e37e15c50261)) 151 | 152 | ## [0.5.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.4.0...v0.5.0) (2021-09-02) 153 | 154 | 155 | ### ⚠ BREAKING CHANGES 156 | 157 | * The `run`, `run_with`, `join`, and `join_with` 158 | functions have been removed. Instead use `Launch::run` or `Join::run`. 159 | These structs can be constructed via the `StructOpt` constructors. 160 | 161 | ### Bug Fixes 162 | 163 | * Use `Launch::is_local` to skip IGD ([173fb4b](https://github.com/maidsafe/sn_launch_tool/commit/173fb4bdcabb2b76ee27cd653f9674ba9db73c90)) 164 | 165 | 166 | * Change API to use argument structs as entrypoints ([78627fa](https://github.com/maidsafe/sn_launch_tool/commit/78627fafe7c640482cd9626f087493b571be3e8f)) 167 | 168 | ## [0.4.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.3.2...v0.4.0) (2021-09-01) 169 | 170 | 171 | ### ⚠ BREAKING CHANGES 172 | 173 | * The `verbosity` argument has been removed. 174 | * The public functions `run`, `run_with`, `join`, and 175 | `join_with` all now return `eyre::Result<()>`, rather than `Result<(), 176 | String>`. 177 | 178 | * Use `eyre` for errors ([b944a92](https://github.com/maidsafe/sn_launch_tool/commit/b944a92783646f1335a6ddf3cec2de5fbc244477)) 179 | * Use `tracing` for all messages ([068eedd](https://github.com/maidsafe/sn_launch_tool/commit/068eedd73a51abdb00a411526604167508ee6868)) 180 | 181 | ### [0.3.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.3.1...v0.3.2) (2021-07-19) 182 | 183 | 184 | ### Features 185 | 186 | * Adding nodes ([19e85a5](https://github.com/maidsafe/sn_launch_tool/commit/19e85a50ed820fcca3900ce37ee3ae5f073ab693)) 187 | 188 | 189 | ### Bug Fixes 190 | 191 | * added nodes use new log dirs ([da316a3](https://github.com/maidsafe/sn_launch_tool/commit/da316a3a338a16ebf569b63e9ec7c8e72dacfed7)) 192 | 193 | ### [0.3.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.3.0...v0.3.1) (2021-07-01) 194 | 195 | 196 | ### Features 197 | 198 | * **args:** add clear-data arg ([7fef81a](https://github.com/maidsafe/sn_launch_tool/commit/7fef81a99fc4052f8b00f977197b7fbee0d7c571)) 199 | * **args:** take local and public ip args ([98b7930](https://github.com/maidsafe/sn_launch_tool/commit/98b793048bf43c403563d96f8d62fd10b46ed4b9)) 200 | 201 | ## [0.3.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.2.3...v0.3.0) (2021-06-23) 202 | 203 | 204 | ### ⚠ BREAKING CHANGES 205 | 206 | * safe_network not sn_node for logging 207 | 208 | ### Features 209 | 210 | * update default log for safe_network ([39c179b](https://github.com/maidsafe/sn_launch_tool/commit/39c179b2622ffee12a66e489a8b2e7b41a126cda)) 211 | 212 | ### [0.2.3](https://github.com/maidsafe/sn_launch_tool/compare/v0.2.2...v0.2.3) (2021-06-17) 213 | 214 | ### [0.2.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.2.1...v0.2.2) (2021-06-08) 215 | 216 | ### [0.2.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.2.0...v0.2.1) (2021-04-26) 217 | 218 | 219 | ### Features 220 | 221 | * **args:** make aware of max capacity argument ([f9e241e](https://github.com/maidsafe/sn_launch_tool/commit/f9e241ed5f7e9331075901dc1ca32af17cfec168)) 222 | 223 | ## [0.2.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.1.0...v0.2.0) (2021-04-05) 224 | 225 | 226 | ### ⚠ BREAKING CHANGES 227 | 228 | * **args:** this uses the args for the latest sn_node 229 | 230 | * **args:** update using the latest node args ([557c950](https://github.com/maidsafe/sn_launch_tool/commit/557c9507ce32d170aa3820f321fc40127a04fdf3)) 231 | 232 | ## [0.1.0](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.20...v0.1.0) (2021-04-01) 233 | 234 | 235 | ### ⚠ BREAKING CHANGES 236 | 237 | * **args:** the new argument is for the latest version of sn_node 238 | 239 | ### update 240 | 241 | * **args:** update args passed for the latest version of sn_node ([1fd88fb](https://github.com/maidsafe/sn_launch_tool/commit/1fd88fb099e0fd533b0a1f48af6c9b1d2341a8f2)) 242 | 243 | ### [0.0.20](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.19...v0.0.20) (2021-03-31) 244 | 245 | ### [0.0.19](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.18...v0.0.19) (2021-03-03) 246 | 247 | ### [0.0.18](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.17...v0.0.18) (2021-02-25) 248 | 249 | ### [0.0.17](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.16...v0.0.17) (2021-02-25) 250 | 251 | 252 | ### Bug Fixes 253 | 254 | * **ip:** changes to support latest version of sn_node which renamed --ip arg to --local-ip ([5d7a000](https://github.com/maidsafe/sn_launch_tool/commit/5d7a000193f980e52b765b6c8106bb3436d2ab69)) 255 | 256 | ### [0.0.16](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.15...v0.0.16) (2021-02-18) 257 | 258 | 259 | ### Bug Fixes 260 | 261 | * set rust_log correctly ([68f64e0](https://github.com/maidsafe/sn_launch_tool/commit/68f64e097016dc06e3603141d68b14d39470d2fe)) 262 | 263 | ### [0.0.15](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.14...v0.0.15) (2021-02-09) 264 | 265 | 266 | ### Features 267 | 268 | * **join:** allow to join to network with a list of addresses rather than a single one ([57ee3b0](https://github.com/maidsafe/sn_launch_tool/commit/57ee3b0979c991e336887709a555d10bb1dd2b96)) 269 | 270 | ### [0.0.14](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.13...v0.0.14) (2021-02-04) 271 | 272 | 273 | ### Features 274 | 275 | * print sn_node version when verbosity is set ([10a226b](https://github.com/maidsafe/sn_launch_tool/commit/10a226bae26cab168458a757447f05959e27c525)) 276 | 277 | ### [0.0.13](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.12...v0.0.13) (2021-02-03) 278 | 279 | ### [0.0.12](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.11...v0.0.12) (2021-02-01) 280 | 281 | ### [0.0.11](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.10...v0.0.11) (2021-01-27) 282 | 283 | 284 | ### Features 285 | 286 | * allow override of RUST_LOG env var for ndoe startup ([99daa5b](https://github.com/maidsafe/sn_launch_tool/commit/99daa5b9b6af1a082da03d4678c76b8ff563d4dd)) 287 | 288 | ### [0.0.10](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.9...v0.0.10) (2021-01-26) 289 | 290 | ### [0.0.9](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.8...v0.0.9) (2021-01-21) 291 | 292 | 293 | ### Features 294 | 295 | * improve network lag w/ node startup options ([6cecb63](https://github.com/maidsafe/sn_launch_tool/commit/6cecb63c24ef91acae8a0f22d4bb4f9b29c19539)) 296 | * log common args on network launch ([57322b2](https://github.com/maidsafe/sn_launch_tool/commit/57322b2c4a2e91278722b3df94654b6672a871b0)) 297 | 298 | ### [0.0.8](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.7...v0.0.8) (2021-01-14) 299 | 300 | ### [0.0.7](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.6...v0.0.7) (2020-12-26) 301 | 302 | 303 | ### Bug Fixes 304 | 305 | * **publish:** fix publish command by adding flag ([4b97eca](https://github.com/maidsafe/sn_launch_tool/commit/4b97ecaf09f734fe87b25b8ec29aae2a7355989b)) 306 | 307 | ### [0.0.6](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.5...v0.0.6) (2020-12-24) 308 | 309 | ### [0.0.5](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.4...v0.0.5) (2020-11-30) 310 | 311 | ### [0.0.4](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.3...v0.0.4) (2020-11-23) 312 | 313 | ### [0.0.3](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.2...v0.0.3) (2020-10-08) 314 | 315 | ### [0.0.2](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.1...v0.0.2) (2020-09-29) 316 | 317 | 318 | ### Features 319 | 320 | * **audit:** add scheduled security audit scan ([90cc5e2](https://github.com/maidsafe/sn_launch_tool/commit/90cc5e2df5177a114c638077d3e5f0b0c164ccbc)) 321 | * **tool:** add option to join the existing network ([b33f455](https://github.com/maidsafe/sn_launch_tool/commit/b33f4556e1e20f48ceaf9dd55222a415f77fc0df)) 322 | * **tool:** support phase-2b vaults ([b1b73f0](https://github.com/maidsafe/sn_launch_tool/commit/b1b73f06f336728316e87abbd7fa71ab2723d391)) 323 | 324 | 325 | ### Bug Fixes 326 | 327 | * **tool:** use hardcoded contact ip in correct format ([6f5d277](https://github.com/maidsafe/sn_launch_tool/commit/6f5d277502078ab08acbaa1346e14c5b6167cd66)) 328 | 329 | ### [0.0.1](https://github.com/maidsafe/sn_launch_tool/compare/v0.0.1...v0.0.1) (2020-02-24) 330 | * Initial implementation 331 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.17.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "atty" 22 | version = "0.2.14" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 25 | dependencies = [ 26 | "hermit-abi", 27 | "libc", 28 | "winapi", 29 | ] 30 | 31 | [[package]] 32 | name = "autocfg" 33 | version = "1.1.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 36 | 37 | [[package]] 38 | name = "backtrace" 39 | version = "0.3.66" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" 42 | dependencies = [ 43 | "addr2line", 44 | "cc", 45 | "cfg-if", 46 | "libc", 47 | "miniz_oxide", 48 | "object", 49 | "rustc-demangle", 50 | ] 51 | 52 | [[package]] 53 | name = "bitflags" 54 | version = "1.3.2" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 57 | 58 | [[package]] 59 | name = "cc" 60 | version = "1.0.75" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "41ca34107f97baef6cfb231b32f36115781856b8f8208e8c580e0bcaea374842" 63 | 64 | [[package]] 65 | name = "cfg-if" 66 | version = "1.0.0" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 69 | 70 | [[package]] 71 | name = "clap" 72 | version = "3.2.23" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" 75 | dependencies = [ 76 | "atty", 77 | "bitflags", 78 | "clap_derive", 79 | "clap_lex", 80 | "indexmap", 81 | "once_cell", 82 | "strsim", 83 | "termcolor", 84 | "textwrap", 85 | ] 86 | 87 | [[package]] 88 | name = "clap_derive" 89 | version = "3.2.18" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" 92 | dependencies = [ 93 | "heck", 94 | "proc-macro-error", 95 | "proc-macro2", 96 | "quote", 97 | "syn", 98 | ] 99 | 100 | [[package]] 101 | name = "clap_lex" 102 | version = "0.2.4" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 105 | dependencies = [ 106 | "os_str_bytes", 107 | ] 108 | 109 | [[package]] 110 | name = "color-eyre" 111 | version = "0.6.2" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" 114 | dependencies = [ 115 | "backtrace", 116 | "color-spantrace", 117 | "eyre", 118 | "indenter", 119 | "once_cell", 120 | "owo-colors", 121 | "tracing-error", 122 | ] 123 | 124 | [[package]] 125 | name = "color-spantrace" 126 | version = "0.2.0" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" 129 | dependencies = [ 130 | "once_cell", 131 | "owo-colors", 132 | "tracing-core", 133 | "tracing-error", 134 | ] 135 | 136 | [[package]] 137 | name = "dirs-next" 138 | version = "2.0.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 141 | dependencies = [ 142 | "cfg-if", 143 | "dirs-sys-next", 144 | ] 145 | 146 | [[package]] 147 | name = "dirs-sys-next" 148 | version = "0.1.2" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 151 | dependencies = [ 152 | "libc", 153 | "redox_users", 154 | "winapi", 155 | ] 156 | 157 | [[package]] 158 | name = "eyre" 159 | version = "0.6.8" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" 162 | dependencies = [ 163 | "indenter", 164 | "once_cell", 165 | ] 166 | 167 | [[package]] 168 | name = "getrandom" 169 | version = "0.2.8" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 172 | dependencies = [ 173 | "cfg-if", 174 | "libc", 175 | "wasi", 176 | ] 177 | 178 | [[package]] 179 | name = "gimli" 180 | version = "0.26.2" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" 183 | 184 | [[package]] 185 | name = "hashbrown" 186 | version = "0.12.3" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 189 | 190 | [[package]] 191 | name = "heck" 192 | version = "0.4.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 195 | 196 | [[package]] 197 | name = "hermit-abi" 198 | version = "0.1.19" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 201 | dependencies = [ 202 | "libc", 203 | ] 204 | 205 | [[package]] 206 | name = "indenter" 207 | version = "0.3.3" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" 210 | 211 | [[package]] 212 | name = "indexmap" 213 | version = "1.9.1" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" 216 | dependencies = [ 217 | "autocfg", 218 | "hashbrown", 219 | ] 220 | 221 | [[package]] 222 | name = "lazy_static" 223 | version = "1.4.0" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 226 | 227 | [[package]] 228 | name = "libc" 229 | version = "0.2.137" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" 232 | 233 | [[package]] 234 | name = "log" 235 | version = "0.4.17" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 238 | dependencies = [ 239 | "cfg-if", 240 | ] 241 | 242 | [[package]] 243 | name = "memchr" 244 | version = "2.5.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 247 | 248 | [[package]] 249 | name = "miniz_oxide" 250 | version = "0.5.4" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" 253 | dependencies = [ 254 | "adler", 255 | ] 256 | 257 | [[package]] 258 | name = "nu-ansi-term" 259 | version = "0.46.0" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 262 | dependencies = [ 263 | "overload", 264 | "winapi", 265 | ] 266 | 267 | [[package]] 268 | name = "object" 269 | version = "0.29.0" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" 272 | dependencies = [ 273 | "memchr", 274 | ] 275 | 276 | [[package]] 277 | name = "once_cell" 278 | version = "1.16.0" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" 281 | 282 | [[package]] 283 | name = "os_str_bytes" 284 | version = "6.3.1" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9" 287 | 288 | [[package]] 289 | name = "overload" 290 | version = "0.1.1" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 293 | 294 | [[package]] 295 | name = "owo-colors" 296 | version = "3.5.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" 299 | 300 | [[package]] 301 | name = "pin-project-lite" 302 | version = "0.2.9" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 305 | 306 | [[package]] 307 | name = "proc-macro-error" 308 | version = "1.0.4" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 311 | dependencies = [ 312 | "proc-macro-error-attr", 313 | "proc-macro2", 314 | "quote", 315 | "syn", 316 | "version_check", 317 | ] 318 | 319 | [[package]] 320 | name = "proc-macro-error-attr" 321 | version = "1.0.4" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 324 | dependencies = [ 325 | "proc-macro2", 326 | "quote", 327 | "version_check", 328 | ] 329 | 330 | [[package]] 331 | name = "proc-macro2" 332 | version = "1.0.47" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" 335 | dependencies = [ 336 | "unicode-ident", 337 | ] 338 | 339 | [[package]] 340 | name = "quote" 341 | version = "1.0.21" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 344 | dependencies = [ 345 | "proc-macro2", 346 | ] 347 | 348 | [[package]] 349 | name = "redox_syscall" 350 | version = "0.2.16" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 353 | dependencies = [ 354 | "bitflags", 355 | ] 356 | 357 | [[package]] 358 | name = "redox_users" 359 | version = "0.4.3" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 362 | dependencies = [ 363 | "getrandom", 364 | "redox_syscall", 365 | "thiserror", 366 | ] 367 | 368 | [[package]] 369 | name = "rustc-demangle" 370 | version = "0.1.21" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 373 | 374 | [[package]] 375 | name = "sharded-slab" 376 | version = "0.1.4" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 379 | dependencies = [ 380 | "lazy_static", 381 | ] 382 | 383 | [[package]] 384 | name = "smallvec" 385 | version = "1.10.0" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 388 | 389 | [[package]] 390 | name = "sn_launch_tool" 391 | version = "0.13.1" 392 | dependencies = [ 393 | "clap", 394 | "color-eyre", 395 | "dirs-next", 396 | "eyre", 397 | "tracing", 398 | "tracing-subscriber", 399 | ] 400 | 401 | [[package]] 402 | name = "strsim" 403 | version = "0.10.0" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 406 | 407 | [[package]] 408 | name = "syn" 409 | version = "1.0.103" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" 412 | dependencies = [ 413 | "proc-macro2", 414 | "quote", 415 | "unicode-ident", 416 | ] 417 | 418 | [[package]] 419 | name = "termcolor" 420 | version = "1.1.3" 421 | source = "registry+https://github.com/rust-lang/crates.io-index" 422 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 423 | dependencies = [ 424 | "winapi-util", 425 | ] 426 | 427 | [[package]] 428 | name = "textwrap" 429 | version = "0.16.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" 432 | 433 | [[package]] 434 | name = "thiserror" 435 | version = "1.0.37" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" 438 | dependencies = [ 439 | "thiserror-impl", 440 | ] 441 | 442 | [[package]] 443 | name = "thiserror-impl" 444 | version = "1.0.37" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" 447 | dependencies = [ 448 | "proc-macro2", 449 | "quote", 450 | "syn", 451 | ] 452 | 453 | [[package]] 454 | name = "thread_local" 455 | version = "1.1.4" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 458 | dependencies = [ 459 | "once_cell", 460 | ] 461 | 462 | [[package]] 463 | name = "tracing" 464 | version = "0.1.37" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 467 | dependencies = [ 468 | "cfg-if", 469 | "pin-project-lite", 470 | "tracing-attributes", 471 | "tracing-core", 472 | ] 473 | 474 | [[package]] 475 | name = "tracing-attributes" 476 | version = "0.1.23" 477 | source = "registry+https://github.com/rust-lang/crates.io-index" 478 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 479 | dependencies = [ 480 | "proc-macro2", 481 | "quote", 482 | "syn", 483 | ] 484 | 485 | [[package]] 486 | name = "tracing-core" 487 | version = "0.1.30" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 490 | dependencies = [ 491 | "once_cell", 492 | "valuable", 493 | ] 494 | 495 | [[package]] 496 | name = "tracing-error" 497 | version = "0.2.0" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" 500 | dependencies = [ 501 | "tracing", 502 | "tracing-subscriber", 503 | ] 504 | 505 | [[package]] 506 | name = "tracing-log" 507 | version = "0.1.3" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 510 | dependencies = [ 511 | "lazy_static", 512 | "log", 513 | "tracing-core", 514 | ] 515 | 516 | [[package]] 517 | name = "tracing-subscriber" 518 | version = "0.3.16" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" 521 | dependencies = [ 522 | "nu-ansi-term", 523 | "sharded-slab", 524 | "smallvec", 525 | "thread_local", 526 | "tracing-core", 527 | "tracing-log", 528 | ] 529 | 530 | [[package]] 531 | name = "unicode-ident" 532 | version = "1.0.5" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 535 | 536 | [[package]] 537 | name = "valuable" 538 | version = "0.1.0" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 541 | 542 | [[package]] 543 | name = "version_check" 544 | version = "0.9.4" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 547 | 548 | [[package]] 549 | name = "wasi" 550 | version = "0.11.0+wasi-snapshot-preview1" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 553 | 554 | [[package]] 555 | name = "winapi" 556 | version = "0.3.9" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 559 | dependencies = [ 560 | "winapi-i686-pc-windows-gnu", 561 | "winapi-x86_64-pc-windows-gnu", 562 | ] 563 | 564 | [[package]] 565 | name = "winapi-i686-pc-windows-gnu" 566 | version = "0.4.0" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 569 | 570 | [[package]] 571 | name = "winapi-util" 572 | version = "0.1.5" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 575 | dependencies = [ 576 | "winapi", 577 | ] 578 | 579 | [[package]] 580 | name = "winapi-x86_64-pc-windows-gnu" 581 | version = "0.4.0" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 584 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sn_launch_tool" 3 | version = "0.13.1" 4 | description = "SAFE API" 5 | authors = [ "Gabriel Viganotti " ] 6 | license = "MIT OR BSD-3-Clause" 7 | repository = "https://github.com/maidsafe/sn_launch_tool.git" 8 | edition = "2018" 9 | 10 | [dependencies] 11 | color-eyre = "~0.6.0" 12 | dirs-next = "2.0" 13 | eyre = "~0.6.5" 14 | clap = { version = "3.0.0", features = ["derive", "env"] } 15 | tracing = "~0.1.26" 16 | tracing-subscriber = "~0.3.1" 17 | -------------------------------------------------------------------------------- /LICENSE-BSD: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, MaidSafe 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 MaidSafe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Safe Network Launch Tool 2 | A cross-platform tool to easily launch a Safe Network test section from home 3 | 4 | ## Installing the Safe Network Node 5 | 6 | A local Safe network is bootstrapped by running several [Safe nodes](https://github.com/maidsafe/safe_network/tree/main/sn_node) which automatically interconnect forming a network. 7 | 8 | In order to run your own local network you'd need to follow these steps: 9 | - Download the latest sn_node [release](https://github.com/maidsafe/safe_network/releases) 10 | - Untar/unzip the downloaded file into a directory of your choice 11 | - Execute this tool specifying the path of the `sn_node` executable 12 | 13 | The following is an example of how to perform this on Linux or Mac: 14 | ```shell 15 | $ mkdir ~/my-local-network 16 | $ cd ~/my-local-network 17 | $ curl -LO https://github.com/maidsafe/safe_network/releases/download/0.8.2-0.7.1-0.68.2-0.64.2-0.66.3-0.59.3/sn_node-0.64.2-x86_64-unknown-linux-musl.tar.gz 18 | $ tar -xzvf sn_node-0.64.2-x86_64-unknown-linux-musl.tar.gz 19 | ``` 20 | 21 | ## Run a local network 22 | 23 | At current state of the [Safe project](), a single-section Safe network can be launched locally in our system. If the Safe node binary was downloaded and extracted at `~/my-local-network/` as described above, we can now launch the network using this tool following these steps: 24 | ```shell 25 | $ git clone https://github.com/maidsafe/sn_launch_tool 26 | $ cd sn_launch_tool 27 | $ cargo run -- --local --num-nodes 15 --node-path ~/my-local-network/sn_node --nodes-dir ~/my-local-network/nodes 28 | 2022-07-11T10:24:47.007035Z INFO sn_launch_tool: Using RUST_LOG 'safe_network=debug' 29 | Starting logging to directory: "/home/me/my-local-network/nodes/sn-node-genesis" 30 | Node PID: 74681, prefix: Prefix(), name: 031758(00000011).., age: 255, connection info: 31 | "127.0.0.1:46641" 32 | 2022-07-11T10:24:49.107884Z INFO sn_launch_tool: Launching nodes 2..=15 33 | Starting logging to directory: "/home/me/my-local-network/nodessn-node-2" 34 | Node PID: 74718, prefix: Prefix(), name: 8d3072(10001101).., age: 98, connection info: 35 | "127.0.0.1:57299" 36 | Starting logging to directory: "/home/me/my-local-network/nodes/sn-node-3" 37 | Node PID: 74755, prefix: Prefix(), name: 0f31a0(00001111).., age: 96, connection info: 38 | "127.0.0.1:36822" 39 | Starting logging to directory: "/home/me/my-local-network/nodes/sn-node-4" 40 | Starting logging to directory: "/home/me/my-local-network/nodes/sn-node-5" 41 | Node PID: 74819, prefix: Prefix(), name: f6bda3(11110110).., age: 94, connection info: 42 | "127.0.0.1:50413" 43 | Starting logging to directory: "/home/me/my-local-network/nodes/sn-node-6" 44 | Node PID: 74856, prefix: Prefix(), name: 757076(01110101).., age: 92, connection info: 45 | "127.0.0.1:46653" 46 | Starting logging to directory: "/home/me/my-local-network/nodes/sn-node-7" 47 | Node PID: 74899, prefix: Prefix(), name: b493f4(10110100).., age: 90, connection info: 48 | "127.0.0.1:60569" 49 | ... 50 | 2022-07-11T10:26:49.537676Z INFO sn_launch_tool: Done 51 | ``` 52 | 53 | Once the local network is running, the connection configuration file will be already in the correct place for your applications to connect to this network, so you can simply run any application from this moment on to connect to your local network. Note that depending on the application, you may need to restart it so it uses the new connection information for your local network. 54 | 55 | In order to shutdown a running local network, all processes instances of sn_node must be killed, e.g. on Linux or Mac you can use the `killall` command: 56 | ```shell 57 | $ killall sn_node 58 | ``` 59 | 60 | This tool allows you to change default values to customise part of the process, you can use the `--help` flag to get a complete list of the flags and options it supports: 61 | ```shell 62 | sn_launch_tool 0.10.0 63 | Tool to launch Safe nodes to form a local single-section network 64 | 65 | Currently, this tool runs nodes on localhost (since that's the default if no IP address is given to 66 | the nodes) 67 | 68 | USAGE: 69 | sn_launch_tool [OPTIONS] 70 | 71 | OPTIONS: 72 | --add 73 | IP used to launch the nodes with 74 | 75 | -d, --nodes-dir 76 | Path where the output directories for all the nodes are written 77 | 78 | [default: ./nodes] 79 | 80 | --flame 81 | Run the nodes using `cargo flamegraph` (which needs to be preinstalled.) It is 82 | recommended to manually run `cargo flamegraph --root --bin=sn_node -- --first` to ensure 83 | everything is built. (This command will fail dur to insufficient args, but that's okay, 84 | carry testnetting w/ --flame thereafter) 85 | 86 | -h, --help 87 | Print help information 88 | 89 | -i, --interval 90 | Interval in milliseconds between launching each of the nodes 91 | 92 | [default: 100] 93 | 94 | --idle-timeout-msec 95 | Interval in seconds before deeming a peer to have timed out 96 | 97 | --ip 98 | IP used to launch the nodes with 99 | 100 | --json-logs 101 | Output logs in json format for easier processing 102 | 103 | --keep-alive-interval-msec 104 | Interval in seconds between qp2p keep alive messages 105 | 106 | -l, --rust-log 107 | RUST_LOG env var value to launch the nodes with 108 | 109 | --local 110 | Run the section locally 111 | 112 | -n, --num-nodes 113 | Number of nodes to spawn with the first one being the genesis. This number should be 114 | greater than 0 115 | 116 | [env: NODE_COUNT=] 117 | [default: 15] 118 | 119 | -p, --node-path 120 | Path where to locate sn_node/sn_node.exe binary. The SN_NODE_PATH env var can be also 121 | used to set the path 122 | 123 | [env: SN_NODE_PATH=] 124 | 125 | -V, --version 126 | Print version information 127 | 128 | -y, --nodes-verbosity 129 | Verbosity level for nodes logs (default: INFO) 130 | 131 | ``` 132 | 133 | ## License 134 | 135 | This Safe Network tool is dual-licensed under the Modified BSD ([LICENSE-BSD](LICENSE-BSD) https://opensource.org/licenses/BSD-3-Clause) or the MIT license ([LICENSE-MIT](LICENSE-MIT) https://opensource.org/licenses/MIT) at your option. 136 | 137 | ## Contributing 138 | 139 | Want to contribute? Great :tada: 140 | 141 | There are many ways to give back to the project, whether it be writing new code, fixing bugs, or just reporting errors. All forms of contributions are encouraged! 142 | 143 | For instructions on how to contribute, see our [Guide to contributing](https://github.com/maidsafe/QA/blob/master/CONTRIBUTING.md). 144 | -------------------------------------------------------------------------------- /codeowners: -------------------------------------------------------------------------------- 1 | * @lionel1704 @bochaco 2 | -------------------------------------------------------------------------------- /src/cmd.rs: -------------------------------------------------------------------------------- 1 | use eyre::{eyre, Result, WrapErr}; 2 | use std::{ 3 | borrow::Cow, 4 | ffi::{OsStr, OsString}, 5 | fmt, 6 | path::Path, 7 | process::{Command, Stdio}, 8 | thread, 9 | time::Duration, 10 | }; 11 | use tracing::{debug, trace}; 12 | 13 | const NODE_LIVENESS_TIMEOUT: Duration = Duration::from_secs(2); 14 | 15 | #[derive(Clone)] 16 | pub(crate) struct NodeCmd<'a> { 17 | path: Cow<'a, OsStr>, 18 | envs: Vec<(Cow<'a, OsStr>, Cow<'a, OsStr>)>, 19 | args: NodeArgs<'a>, 20 | // run w/ flamegraph 21 | flame: bool, 22 | } 23 | 24 | impl<'a> NodeCmd<'a> { 25 | pub(crate) fn new(path: P) -> Self 26 | where 27 | P: Into>, 28 | Pb: AsRef + ToOwned + ?Sized + 'a, 29 | Pb::Owned: Into, 30 | { 31 | Self { 32 | path: into_cow_os_str(path), 33 | envs: Default::default(), 34 | args: Default::default(), 35 | flame: false, 36 | } 37 | } 38 | 39 | pub(crate) fn path(&self) -> &Path { 40 | Path::new(&self.path) 41 | } 42 | 43 | pub(crate) fn set_flame(&mut self, flame: bool) { 44 | self.flame = flame 45 | } 46 | 47 | pub(crate) fn gen_flamegraph(&self) -> bool { 48 | self.flame 49 | } 50 | 51 | pub(crate) fn args(&self) -> &NodeArgs { 52 | &self.args 53 | } 54 | 55 | pub(crate) fn push_env(&mut self, key: K, value: V) 56 | where 57 | K: Into>, 58 | Kb: AsRef + ToOwned + ?Sized + 'a, 59 | Kb::Owned: Into, 60 | V: Into>, 61 | Vb: AsRef + ToOwned + ?Sized + 'a, 62 | Vb::Owned: Into, 63 | { 64 | self.envs 65 | .push((into_cow_os_str(key), into_cow_os_str(value))); 66 | } 67 | 68 | pub(crate) fn push_arg(&mut self, arg: A) 69 | where 70 | A: Into>, 71 | B: AsRef + ToOwned + ?Sized + 'a, 72 | B::Owned: Into, 73 | { 74 | self.args.push(arg); 75 | } 76 | 77 | pub(crate) fn version(&self) -> Result { 78 | let version = Command::new(&self.path) 79 | .args(["-V"]) 80 | .output() 81 | .map_or_else( 82 | |error| Err(eyre!(error)), 83 | |output| { 84 | if output.status.success() { 85 | Ok(output.stdout) 86 | } else { 87 | Err(eyre!( 88 | "Process exited with non-zero status (status: {}, stderr: {})", 89 | output.status, 90 | String::from_utf8_lossy(&output.stderr) 91 | )) 92 | } 93 | }, 94 | ) 95 | .wrap_err_with(|| { 96 | format!( 97 | "Failed to run '{}' with args '{:?}'", 98 | self.path().display(), 99 | &["-V"] 100 | ) 101 | })?; 102 | 103 | Ok(String::from_utf8_lossy(&version).trim().to_string()) 104 | } 105 | 106 | pub(crate) fn run(&self, node_name: &str, node_dir: &Path) -> Result<()> { 107 | let node_dir = node_dir.join(node_name); 108 | 109 | let mut cmd = self.path().display().to_string(); 110 | 111 | let flame_on = self.gen_flamegraph(); 112 | let graph_output = format!("-o {node_name}-flame.svg"); 113 | 114 | if flame_on { 115 | cmd = "cargo".to_string(); 116 | // make a dir per node 117 | std::fs::create_dir_all(node_name)?; 118 | debug!("Flame graph will be stored: {:?}", graph_output); 119 | } 120 | 121 | trace!("Running '{cmd}' with args {:?} ...", self.args); 122 | 123 | let mut extra_args = NodeArgs::default(); 124 | extra_args.push("--root-dir"); 125 | extra_args.push(node_dir.clone()); 126 | extra_args.push("--log-dir"); 127 | extra_args.push(node_dir); 128 | 129 | let mut the_cmd = Command::new(cmd.clone()); 130 | let additonal_flame_args = vec![ 131 | "flamegraph", 132 | &graph_output, 133 | "--root", 134 | "--bin", 135 | "sn_node", 136 | "--", 137 | ]; 138 | if flame_on { 139 | debug!("Launching nodes via `cargo flamegraph`"); 140 | // we set the command ro run in each individal node dir (as each flamegraph uses a file `cargo-flamegraph.stacks` which cannot be renamed per per node) 141 | // we set flamegraph to root as that's necesasry on mac 142 | the_cmd 143 | .current_dir(node_name) 144 | .args(additonal_flame_args.clone()); 145 | } 146 | 147 | the_cmd 148 | .args(&self.args) 149 | .args(&extra_args) 150 | .envs(self.envs.iter().map( 151 | // this looks like a no-op but really converts `&(_, _)` into `(_, _)` 152 | |(key, value)| (key, value), 153 | )) 154 | .stdout(Stdio::inherit()) 155 | .stderr(Stdio::inherit()) 156 | .spawn() 157 | .map_err(|error| eyre!(error)) 158 | .and_then(|mut child| { 159 | // Wait a couple of seconds to see if the node fails immediately, so we can fail fast 160 | thread::sleep(NODE_LIVENESS_TIMEOUT); 161 | 162 | if let Some(status) = child.try_wait()? { 163 | return Err(eyre!("Node exited early (status: {})", status)); 164 | } 165 | 166 | Ok(()) 167 | }) 168 | .wrap_err_with(|| { 169 | let mut all_args = vec![]; 170 | if flame_on { 171 | // all_args.extend(additonal_flame_args); 172 | 173 | for arg in additonal_flame_args { 174 | let c = into_cow_os_str(arg); 175 | all_args.push(c); 176 | } 177 | } 178 | 179 | for arg in self.args.into_iter() { 180 | all_args.push(arg.clone()); 181 | } 182 | for arg in extra_args.into_iter() { 183 | all_args.push(arg.clone()); 184 | } 185 | 186 | format!("Failed to start '{cmd}' with args '{all_args:?}'") 187 | })?; 188 | 189 | Ok(()) 190 | } 191 | } 192 | 193 | #[derive(Clone, Default)] 194 | pub(crate) struct NodeArgs<'a>(Vec>); 195 | 196 | impl<'a> NodeArgs<'a> { 197 | fn push(&mut self, arg: A) 198 | where 199 | A: Into>, 200 | B: AsRef + ToOwned + ?Sized + 'a, 201 | B::Owned: Into, 202 | { 203 | self.0.push(into_cow_os_str(arg)); 204 | } 205 | } 206 | 207 | impl<'a> IntoIterator for &'a NodeArgs<'a> { 208 | type Item = &'a Cow<'a, OsStr>; 209 | 210 | type IntoIter = std::slice::Iter<'a, Cow<'a, OsStr>>; 211 | 212 | fn into_iter(self) -> Self::IntoIter { 213 | self.0.iter() 214 | } 215 | } 216 | 217 | impl<'a> fmt::Debug for NodeArgs<'a> { 218 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 219 | f.debug_list() 220 | .entries(self.0.iter().map(|arg| -> &OsStr { arg.as_ref() })) 221 | .finish() 222 | } 223 | } 224 | 225 | fn into_cow_os_str<'a, V, Vb>(val: V) -> Cow<'a, OsStr> 226 | where 227 | V: Into>, 228 | Vb: AsRef + ToOwned + ?Sized + 'a, 229 | Vb::Owned: Into, 230 | { 231 | match val.into() { 232 | Cow::Borrowed(val) => val.as_ref().into(), 233 | Cow::Owned(val) => val.into().into(), 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | mod cmd; 11 | 12 | use eyre::{eyre, Result, WrapErr}; 13 | use std::{ 14 | borrow::Cow, 15 | env, 16 | fs::{self}, 17 | net::SocketAddr, 18 | ops::RangeInclusive, 19 | path::PathBuf, 20 | thread, 21 | time::Duration, 22 | }; 23 | use tracing::{debug, info}; 24 | 25 | use cmd::NodeCmd; 26 | 27 | #[cfg(not(target_os = "windows"))] 28 | const SN_NODE_EXECUTABLE: &str = "sn_node"; 29 | 30 | #[cfg(target_os = "windows")] 31 | const SN_NODE_EXECUTABLE: &str = "sn_node.exe"; 32 | 33 | const DEFAULT_RUST_LOG: &str = "safe_network=debug"; 34 | 35 | /// Tool to launch Safe nodes to form a local single-section network 36 | /// 37 | /// Currently, this tool runs nodes on localhost (since that's the default if no IP address is given to the nodes) 38 | #[derive(Debug, clap::StructOpt)] 39 | #[clap(version)] 40 | pub struct Launch { 41 | #[clap(flatten)] 42 | common: CommonArgs, 43 | 44 | /// Interval in milliseconds between launching each of the nodes 45 | #[clap(short = 'i', long, default_value = "100", value_parser)] 46 | interval: u64, 47 | 48 | /// Interval in seconds before deeming a peer to have timed out 49 | #[clap(long = "idle-timeout-msec", value_parser)] 50 | idle_timeout_msec: Option, 51 | 52 | /// Interval in seconds between qp2p keep alive messages 53 | #[clap(long = "keep-alive-interval-msec", value_parser)] 54 | keep_alive_interval_msec: Option, 55 | 56 | /// Path where the output directories for all the nodes are written 57 | #[clap(short = 'd', long, default_value = "./nodes", value_parser)] 58 | nodes_dir: PathBuf, 59 | 60 | /// Number of nodes to spawn with the first one being the genesis. This number should be greater than 0. 61 | #[clap( 62 | short = 'n', 63 | long, 64 | default_value = "15", 65 | env = "NODE_COUNT", 66 | value_parser 67 | )] 68 | num_nodes: usize, 69 | 70 | /// IP used to launch the nodes with. 71 | #[clap(long = "ip", value_parser)] 72 | ip: Option, 73 | 74 | /// IP used to launch the nodes with. 75 | #[clap(long = "add", value_parser)] 76 | add_nodes_to_existing_network: bool, 77 | } 78 | 79 | impl Launch { 80 | /// Launch a network with these arguments. 81 | pub fn run(&self) -> Result<()> { 82 | let mut node_cmd = self.common.node_cmd()?; 83 | 84 | if let Some(idle) = self.idle_timeout_msec { 85 | node_cmd.push_arg("--idle-timeout-msec"); 86 | node_cmd.push_arg(idle.to_string()); 87 | } 88 | 89 | if let Some(keep_alive_interval_msec) = self.keep_alive_interval_msec { 90 | node_cmd.push_arg("--keep-alive-interval-msec"); 91 | node_cmd.push_arg(keep_alive_interval_msec.to_string()); 92 | } 93 | 94 | if let Some(ip) = &self.ip { 95 | node_cmd.push_arg("--local-addr"); 96 | node_cmd.push_arg(format!("{ip}:0")); 97 | } else if self.common.is_local { 98 | node_cmd.push_arg("--local-addr"); 99 | node_cmd.push_arg("127.0.0.1:0"); 100 | } 101 | 102 | debug!("Network size: {} nodes", self.num_nodes); 103 | 104 | let interval = Duration::from_millis(self.interval); 105 | 106 | if !self.add_nodes_to_existing_network { 107 | self.run_genesis(&node_cmd)?; 108 | thread::sleep(interval); 109 | 110 | debug!("Genesis wait over..."); 111 | } 112 | 113 | let genesis_contacts_filepath = self.nodes_dir.join("sn-node-genesis").join("section_tree"); 114 | 115 | let node_ids = self.node_ids()?; 116 | if !node_ids.is_empty() { 117 | node_cmd.push_arg("--network-contacts-file"); 118 | node_cmd.push_arg(&genesis_contacts_filepath); 119 | 120 | debug!( 121 | "Common node args for launching the network: {:?}", 122 | node_cmd.args() 123 | ); 124 | info!("Launching nodes {:?}", node_ids); 125 | 126 | for i in node_ids { 127 | self.run_node(&node_cmd, i)?; 128 | thread::sleep(interval); 129 | } 130 | } 131 | 132 | // Let's copy the genesis' section_tree file to the default location for clients to use 133 | let client_network_contacts_dir = dirs_next::home_dir() 134 | .ok_or_else(|| eyre!("Could not read user's home directory".to_string()))? 135 | .join(".safe") 136 | .join("network_contacts"); 137 | 138 | info!( 139 | "Copying network contacts file to {} for local clients to bootstrap to the network", 140 | client_network_contacts_dir.display() 141 | ); 142 | fs::create_dir_all(&client_network_contacts_dir)?; 143 | fs::copy( 144 | genesis_contacts_filepath, 145 | client_network_contacts_dir.join("default"), 146 | )?; 147 | 148 | info!("Done!"); 149 | Ok(()) 150 | } 151 | 152 | fn run_genesis(&self, node_cmd: &NodeCmd) -> Result<()> { 153 | // Set genesis node's command arguments 154 | let mut genesis_cmd = node_cmd.clone(); 155 | genesis_cmd.push_arg("--first"); 156 | // `--first` requires a public address. Port `0` means it will be the same as locally bound port. 157 | if let Some(ip) = &self.ip { 158 | genesis_cmd.push_arg(format!("{ip}:0")); 159 | } else if self.common.is_local { 160 | genesis_cmd.push_arg("127.0.0.1:0"); 161 | } 162 | 163 | // Let's launch genesis node now 164 | debug!("Launching genesis node (#1)..."); 165 | genesis_cmd.run("sn-node-genesis", &self.nodes_dir)?; 166 | 167 | Ok(()) 168 | } 169 | 170 | fn run_node(&self, node_cmd: &NodeCmd, node_idx: usize) -> Result<()> { 171 | if self.add_nodes_to_existing_network { 172 | debug!("Adding node #{}...", node_idx) 173 | } else { 174 | debug!("Launching node #{}...", node_idx) 175 | }; 176 | node_cmd.run(&format!("sn-node-{node_idx}"), &self.nodes_dir)?; 177 | 178 | Ok(()) 179 | } 180 | 181 | fn node_ids(&self) -> Result> { 182 | let paths = 183 | fs::read_dir(&self.nodes_dir).wrap_err("Could not read existing testnet log dir")?; 184 | 185 | let count = paths 186 | .collect::, _>>() 187 | .wrap_err("Error collecting testnet log dir")? 188 | .len(); 189 | 190 | if count == 0 { 191 | return Err(eyre!("A genesis node could not be found.")); 192 | } 193 | 194 | let last_idx: usize = if self.add_nodes_to_existing_network { 195 | count + self.num_nodes 196 | } else { 197 | self.num_nodes 198 | }; 199 | 200 | Ok(count + 1..=last_idx) 201 | } 202 | } 203 | 204 | /// Run a Safe node to join a network 205 | #[derive(Debug, clap::StructOpt)] 206 | pub struct Join { 207 | #[clap(flatten)] 208 | common: CommonArgs, 209 | 210 | /// Path where the output directories for all the nodes are written 211 | #[clap(short = 'd', long, default_value = "./nodes", value_parser)] 212 | nodes_dir: PathBuf, 213 | 214 | /// Max storage to use while running the node 215 | #[clap(short, long, value_parser)] 216 | max_capacity: Option, 217 | 218 | /// Local network address for the node, eg 192.168.1.100:12000 219 | #[clap(long, value_parser)] 220 | local_addr: Option, 221 | 222 | /// Public address for the node 223 | #[clap(long, value_parser)] 224 | public_addr: Option, 225 | 226 | /// Clear data directory created by a previous node run 227 | #[clap(long = "clear-data", value_parser)] 228 | clear_data: bool, 229 | 230 | /// Network contacts list file path 231 | #[clap(long, value_parser)] 232 | network_contacts_file: PathBuf, 233 | } 234 | 235 | impl Join { 236 | /// Join a network with these arguments. 237 | pub fn run(&self) -> Result<()> { 238 | let mut node_cmd = self.common.node_cmd()?; 239 | 240 | if let Some(max_capacity) = self.max_capacity { 241 | node_cmd.push_arg("--max-capacity"); 242 | node_cmd.push_arg(max_capacity.to_string()); 243 | } 244 | 245 | if let Some(local_addr) = self.local_addr { 246 | node_cmd.push_arg("--local-addr"); 247 | node_cmd.push_arg(local_addr.to_string()); 248 | } else if self.common.is_local { 249 | node_cmd.push_arg("--local-addr"); 250 | node_cmd.push_arg("127.0.0.1:0"); 251 | } 252 | 253 | if let Some(public_addr) = self.public_addr { 254 | node_cmd.push_arg("--public-addr"); 255 | node_cmd.push_arg(public_addr.to_string()); 256 | } 257 | 258 | if self.clear_data { 259 | node_cmd.push_arg("--clear-data"); 260 | } 261 | 262 | node_cmd.push_arg("--network-contacts-file"); 263 | node_cmd.push_arg(self.network_contacts_file.clone()); 264 | 265 | debug!("Launching node..."); 266 | node_cmd.run( 267 | "", // no name passed 268 | &self.nodes_dir, 269 | )?; 270 | 271 | debug!( 272 | "Node logs are being stored at: {}/sn_node.log", 273 | self.nodes_dir.display() 274 | ); 275 | debug!("(Note that log files are rotated hourly, and subsequent files will be named sn_node.log."); 276 | 277 | Ok(()) 278 | } 279 | } 280 | 281 | #[derive(Debug, clap::StructOpt)] 282 | struct CommonArgs { 283 | /// Path where to locate sn_node/sn_node.exe binary. The SN_NODE_PATH env var can be also used to set the path 284 | #[clap(short = 'p', long, env = "SN_NODE_PATH", value_parser)] 285 | node_path: Option, 286 | 287 | /// Verbosity level for nodes logs (default: INFO) 288 | #[clap(short = 'y', long, action = clap::ArgAction::Count)] 289 | nodes_verbosity: u8, 290 | 291 | /// RUST_LOG env var value to launch the nodes with. 292 | #[clap(short = 'l', long, value_parser)] 293 | rust_log: Option, 294 | 295 | /// Output logs in json format for easier processing. 296 | #[clap(long, value_parser)] 297 | json_logs: bool, 298 | 299 | /// Run the section locally. 300 | #[clap(long = "local", value_parser)] 301 | is_local: bool, 302 | 303 | /// Run the nodes using `cargo flamegraph` (which needs to be preinstalled.) 304 | /// It is recommended to manually run `cargo flamegraph --root --bin=sn_node -- --first` to ensure 305 | /// everything is built. (This command will fail dur to insufficient args, but that's okay, carry 306 | /// testnetting w/ --flame thereafter) 307 | #[clap(long = "flame", value_parser)] 308 | flame: bool, 309 | } 310 | 311 | impl CommonArgs { 312 | fn node_cmd(&self) -> Result { 313 | let mut cmd = match self.node_path.as_deref() { 314 | Some(p) => NodeCmd::new(p), 315 | None => { 316 | let mut path = 317 | dirs_next::home_dir().ok_or_else(|| eyre!("Home directory not found"))?; 318 | 319 | path.push(".safe/node"); 320 | path.push(SN_NODE_EXECUTABLE); 321 | NodeCmd::new(path) 322 | } 323 | }; 324 | 325 | let rust_log = self.rust_log(); 326 | info!("Using RUST_LOG '{}'", rust_log); 327 | 328 | cmd.push_env("RUST_LOG", rust_log); 329 | cmd.push_arg( 330 | // We need a minimum of INFO level for nodes verbosity, 331 | // since the genesis node logs the contact info at INFO level 332 | format!("-{}", "v".repeat(2 + self.nodes_verbosity as usize)), 333 | ); 334 | 335 | if self.json_logs { 336 | cmd.push_arg("--json-logs"); 337 | } 338 | 339 | if self.flame { 340 | cmd.set_flame(self.flame); 341 | } 342 | 343 | debug!( 344 | "Using sn_node @ {} from {}", 345 | cmd.version()?, 346 | cmd.path().display() 347 | ); 348 | 349 | Ok(cmd) 350 | } 351 | 352 | fn rust_log(&self) -> Cow<'_, str> { 353 | match self.rust_log.as_deref() { 354 | Some(rust_log_flag) => rust_log_flag.into(), 355 | None => match env::var("RUST_LOG") { 356 | Ok(rust_log_env) => rust_log_env.into(), 357 | Err(_) => DEFAULT_RUST_LOG.into(), 358 | }, 359 | } 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 MaidSafe.net limited. 2 | // 3 | // This SAFE Network Software is licensed to you under the MIT license or the Modified BSD license , at your option. This file may not be copied, 6 | // modified, or distributed except according to those terms. Please review the Licences for the 7 | // specific language governing permissions and limitations relating to use of the SAFE Network 8 | // Software. 9 | 10 | use clap::Parser; 11 | use eyre::Result; 12 | use sn_launch_tool::Launch; 13 | use tracing::debug; 14 | 15 | fn main() -> Result<()> { 16 | color_eyre::install()?; 17 | tracing_subscriber::fmt::init(); 18 | 19 | debug!("Launching Safe nodes..."); 20 | 21 | Launch::parse().run() 22 | } 23 | --------------------------------------------------------------------------------