pax_global_header00006660000000000000000000000064142613540330014513gustar00rootroot0000000000000052 comment=20c9f35912b20dc534c792422b3e9285ecb3b96b resource_proof-1.0.39/000077500000000000000000000000001426135403300146415ustar00rootroot00000000000000resource_proof-1.0.39/.github/000077500000000000000000000000001426135403300162015ustar00rootroot00000000000000resource_proof-1.0.39/.github/workflows/000077500000000000000000000000001426135403300202365ustar00rootroot00000000000000resource_proof-1.0.39/.github/workflows/auto_merge_prs.yml000066400000000000000000000021141426135403300237720ustar00rootroot00000000000000# auto merge workflow. # # Auto merge PR if commit msg begins with `chore(release):`, # or if it has been raised by Dependabot. # Uses https://github.com/ridedott/merge-me-action. name: Merge Version Change and Dependabot PRs automatically on: pull_request jobs: merge: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 with: fetch-depth: '0' - name: get commit message run: | commitmsg=$(git log --format=%s -n 1 ${{ github.event.pull_request.head.sha }}) echo "commitmsg=${commitmsg}" >> $GITHUB_ENV - name: show commit message run : echo $commitmsg - name: Merge Version change PR if: startsWith( env.commitmsg, 'chore(release):') uses: ridedott/merge-me-action@81667e6ae186ddbe6d3c3186d27d91afa7475e2c with: GITHUB_LOGIN: dirvine GITHUB_TOKEN: ${{ secrets.MERGE_BUMP_BRANCH_TOKEN }} MERGE_METHOD: REBASE - name: Dependabot Merge uses: ridedott/merge-me-action@master with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MERGE_METHOD: REBASE resource_proof-1.0.39/.github/workflows/bump_version.yml000066400000000000000000000011161426135403300234700ustar00rootroot00000000000000name: Version bump and create PR for changes on: # Trigger the workflow on push only for the master branch push: branches: - master env: NODE_ENV: 'development' jobs: update_changelog: runs-on: ubuntu-20.04 # Dont run if we're on a release commit if: "!startsWith(github.event.head_commit.message, 'chore(release):')" steps: - uses: actions/checkout@v2 with: fetch-depth: '0' - name: Bump Version uses: maidsafe/rust-version-bump-branch-creator@v2 with: token: ${{ secrets.BRANCH_CREATOR_TOKEN }} resource_proof-1.0.39/.github/workflows/commitlint.yml000066400000000000000000000004621426135403300231420ustar00rootroot00000000000000name: Commitlint on: [pull_request] jobs: lint: runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - uses: wagoid/commitlint-github-action@f114310111fdbd07e99f47f9ca13d62b3ec98372 resource_proof-1.0.39/.github/workflows/github_release.yml000066400000000000000000000017111426135403300237430ustar00rootroot00000000000000name: Create GitHub Release on: push: tags: - 'v*' jobs: release: # only if we have a tag name: Release runs-on: ubuntu-20.04 if: "startsWith(github.event.head_commit.message, 'chore(release):')" steps: - uses: actions/checkout@v2 with: fetch-depth: '0' - name: Set tag as env shell: bash run: echo "RELEASE_VERSION=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV - name: lets check tag shell: bash run: echo ${{ env.RELEASE_VERSION }} - name: Generate Changelog shell: bash run: awk '/# \[/{c++;p=1}{if(c==2){exit}}p;' CHANGELOG.md > RELEASE-CHANGELOG.txt - run: cat RELEASE-CHANGELOG.txt - name: Release generation uses: softprops/action-gh-release@91409e712cf565ce9eff10c87a8d1b11b81757ae env: GITHUB_TOKEN: ${{ secrets.MERGE_BUMP_BRANCH_TOKEN }} with: body_path: RELEASE-CHANGELOG.txt resource_proof-1.0.39/.github/workflows/master.yml000066400000000000000000000037041426135403300222600ustar00rootroot00000000000000# Push to master workflow. # # Runs when a PR has been merged to the master branch. # # 1. Generates a release build. # 2. If the last commit is a version change, publish. name: Build and Publish (on tag) on: push: branches: - master env: # Run all cargo commands with --verbose. CARGO_TERM_VERBOSE: true RUST_BACKTRACE: 1 jobs: build: name: Build runs-on: ${{ matrix.os }} if: "startsWith(github.event.head_commit.message, 'chore(release):')" strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v2 # Install Rust - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true # Cache. - name: Cargo cache registry, index and build uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} # Make sure the code builds. - name: Build run: cargo build --release # Publish if we're on a tag here. publish: name: Publish runs-on: ubuntu-latest needs: build if: "startsWith(github.event.head_commit.message, 'chore(release):')" steps: - uses: actions/checkout@v2 # checkout with fetch-depth: '0' to be sure to retrieve all commits to look for the semver commit message with: fetch-depth: '0' ## Install Rust - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true # Publish to crates.io. - uses: actions-rs/cargo@v1 with: command: login args: ${{ secrets.CRATES_IO_TOKEN }} - uses: actions-rs/cargo@v1 with: command: package - uses: actions-rs/cargo@v1 with: command: publish resource_proof-1.0.39/.github/workflows/pr.yml000066400000000000000000000114731426135403300214100ustar00rootroot00000000000000# PR workflow. # # Runs full suite of checks, with warnings treated as errors. # Gather code coverage stats and publish them on coveralls.io. name: PR on: pull_request env: # Run all cargo commands with --verbose. CARGO_TERM_VERBOSE: true RUST_BACKTRACE: 1 # Deny all compiler warnings. RUSTFLAGS: "-D warnings" jobs: checks: if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" name: Clippy & fmt runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Install Rust and required components - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true components: rustfmt, clippy # Cache. - name: Cargo cache registry, index and build uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} # Check if the code is formatted correctly. - name: Check formatting run: cargo fmt --all -- --check # Run Clippy. - name: Clippy checks run: cargo clippy --all-targets check_pr_size: if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" name: Check PR size doesn't break set limit runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: '0' - uses: maidsafe/pr_size_checker@v2 with: max_lines_changed: 200 coverage: if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" name: Code coverage check runs-on: ubuntu-latest env: PROPTEST_CASES: 1 steps: - uses: actions/checkout@v2 # Install Rust - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true # Cache. - name: Cargo cache registry, index and build uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} # Run cargo tarpaulin & push result to coveralls.io - name: rust-tarpaulin code coverage check uses: actions-rs/tarpaulin@v0.1 with: args: '-v -t 300 --release --out Lcov' - name: Push code coverage results to coveralls.io uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel: true path-to-lcov: ./lcov.info - name: Coveralls Finished uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true cargo-udeps: if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" name: Unused dependency check runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Install Rust and required components - uses: actions-rs/toolchain@v1 with: toolchain: nightly override: true - name: Run cargo-udeps uses: aig787/cargo-udeps-action@v1 with: version: 'latest' args: '--all-targets' cargo-deny: if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # wget the shared deny.toml file from the QA repo - shell: bash run: wget https://raw.githubusercontent.com/maidsafe/QA/master/misc-scripts/deny.toml - uses: EmbarkStudios/cargo-deny-action@v1 test: name: Test runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v2 # Install Rust - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true # Cache. - name: Cargo cache registry, index and build uses: actions/cache@v2.1.4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} # Run tests. - name: Cargo test run: cargo test --release # Test publish using --dry-run. test-publish: if: "!startsWith(github.event.pull_request.title, 'Automated version bump')" name: Test Publish runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Install Rust - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - name: Cargo publish dry run run: cargo publish --dry-run resource_proof-1.0.39/.github/workflows/security_audit.yml000066400000000000000000000004451426135403300240210ustar00rootroot00000000000000name: Security audit on: schedule: - cron: '0 0 * * *' jobs: audit: if: github.repository_owner == 'maidsafe' runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} resource_proof-1.0.39/.github/workflows/tag_release.yml000066400000000000000000000025231426135403300232360ustar00rootroot00000000000000name: Tag release commit on: # Trigger the workflow on push only for the master branch push: branches: - master env: NODE_ENV: 'development' GITHUB_TOKEN: ${{ secrets.BRANCH_CREATOR_TOKEN }} jobs: tag: runs-on: ubuntu-latest # Only run on a release commit if: "startsWith(github.event.head_commit.message, 'chore(release):')" steps: - uses: actions/checkout@v2 with: fetch-depth: '0' token: ${{ secrets.BRANCH_CREATOR_TOKEN }} - run: echo "RELEASE_VERSION=$(git log -1 --pretty=%s)" >> $GITHUB_ENV # parse out non-tag text - run: echo "RELEASE_VERSION=$( echo $RELEASE_VERSION | sed 's/chore(release)://' )" >> $GITHUB_ENV # remove spaces, but add back in `v` to tag, which is needed for standard-version - run: echo "RELEASE_VERSION=v$(echo $RELEASE_VERSION | tr -d '[:space:]')" >> $GITHUB_ENV - run: echo $RELEASE_VERSION - run: git tag $RELEASE_VERSION - name: Setup git for push run: | git remote add github "$REPO" git config --local user.email "action@github.com" git config --local user.name "GitHub Action" - name: Push tags to master run: git push "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY" HEAD:master --tags resource_proof-1.0.39/.gitignore000066400000000000000000000000221426135403300166230ustar00rootroot00000000000000target Cargo.lock resource_proof-1.0.39/CHANGELOG.md000066400000000000000000000035241426135403300164560ustar00rootroot00000000000000# Changelog 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. ### [1.0.39](https://github.com/maidsafe/resource_proof/compare/v1.0.38...v1.0.39) (2022-07-06) ### [1.0.38](https://github.com/maidsafe/resource_proof/compare/v1.0.37...v1.0.38) (2021-06-09) ### [1.0.37](https://github.com/maidsafe/resource_proof/compare/v1.0.36...v1.0.37) (2021-02-25) ### [1.0.36](https://github.com/maidsafe/resource_proof/compare/v1.0.35...v1.0.36) (2021-02-11) ### [1.0.35](https://github.com/maidsafe/resource_proof/compare/v1.0.34...v1.0.35) (2021-02-10) ### [1.0.34](https://github.com/maidsafe/resource_proof/compare/v1.0.33...v1.0.34) (2021-02-03) ### [1.0.33](https://github.com/maidsafe/resource_proof/compare/v1.0.32...v1.0.33) (2021-01-20) ### [1.0.32](https://github.com/maidsafe/resource_proof/compare/v1.0.31...v1.0.32) (2021-01-19) ### [1.0.31](https://github.com/maidsafe/resource_proof/compare/v0.8.0...v1.0.31) (2021-01-19) ### [0.8.0](https://github.com/maidsafe/resource_proof/compare/0.7.0...v0.8.0) (2019-09-18) - Update tiny-keccak dependency - Use rust edition 2018 ### [0.7.0](https://github.com/maidsafe/resource_proof/compare/0.6.0...0.7.0) (2019-05-29) - Update clap dependency to the latest version ### [0.6.0](https://github.com/maidsafe/resource_proof/compare/0.5.0...0.6.0) (2018-01-06) - Use rust 1.22.1 stable / 2017-12-02 nightly - rustfmt 0.9.0 and clippy-0.0.175 ### [0.5.0](https://github.com/maidsafe/resource_proof/compare/0.4.0...0.5.0) (2017-07-25) - Use rust 1.19 stable / 2017-07-20 nightly - rustfmt 0.9.0 and clippy-0.0.144 - Replace -Zno-trans with cargo check - Make appveyor script using fixed version of stable ### [0.4.0] (2017-04-05) - Allow trying one step at a time and getting the expected number. resource_proof-1.0.39/Cargo.toml000066400000000000000000000011241426135403300165670ustar00rootroot00000000000000[package] authors = [ "MaidSafe Developers " ] description = "A 'proof' of bandwidth, cpu and storage for nodes in a decentralised network." documentation = "https://docs.rs/resource_proof" homepage = "https://maidsafe.net" license = "MIT OR BSD-3-Clause" name = "resource_proof" readme = "README.md" repository = "https://github.com/maidsafe/resource_proof" version = "1.0.39" edition = "2021" [dependencies.clap] version = "3.0" features = [ "derive" ] [dependencies.tiny-keccak] version = "2.0.2" features = [ "sha3" ] [target."cfg(unix)".dependencies] termion = "~1.5.1" resource_proof-1.0.39/LICENSE-BSD000066400000000000000000000026721426135403300162630ustar00rootroot00000000000000Copyright 2018 MaidSafe.net limited. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. resource_proof-1.0.39/LICENSE-MIT000066400000000000000000000020451426135403300162760ustar00rootroot00000000000000Copyright 2018 MaidSafe.net limited. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. resource_proof-1.0.39/README.md000066400000000000000000000202411426135403300161170ustar00rootroot00000000000000# resource_proof |Crate|Documentation|CI| |:---:|:-----------:|:--------:| |[![](http://meritbadge.herokuapp.com/resource_proof)](https://crates.io/crates/resource_proof)|[![Documentation](https://docs.rs/resource_proof/badge.svg)](https://docs.rs/resource_proof)|![](https://github.com/maidsafe/resource_proof/workflows/Master/badge.svg)| | [MaidSafe website](https://maidsafe.net) | [Safe Dev Forum](https://forum.safedev.org) | [Safe Network Forum](https://safenetforum.org) | |:----------------------------------------:|:-------------------------------------------:|:----------------------------------------------:| ## Summary This crate hopes to combine mechanisms that attempt to validate resources on remote machines. This validation though, is a spot check and also best effort. It is not guaranteed to be accurate over time and this consideration must be clear to users of the crate. The purpose is to provide **some** indication that a machine has **some** capabilities. ## Motivation In decentralised networks where trust is absent a node intending to join has to prove it can meet the minimum requirements of the network. These resource requirements are decided by either the network itself (best) or set by the programmer. In such networks, one must assume the node joining is not running the same software that existing nodes are running. Even if nodes offset this proof by using another resource to aid the proof, it's unlikely to help as the network should use continual monitoring of capability in parallel with these "spot checks". ## Current state At version 0.2.x this crate carries out some rudimentary checks that requires a node has some computing ability and also the ability to transfer a certain amount of data (bandwith check). Based on a variant of [Hashcash](https://en.wikipedia.org/wiki/Hashcash) with the addition of the requirement to transfer an amount of data, this library does provide a "proof of work" like algorithm. This work requirement forces joining nodes to perform some calculation and data transfer. The expected use case is to require the work is done and data transferred within a time duration. It is possible to supply two proofs, one to focus on a large amount of work (difficulty) and another to focus on a bandwidth requirement (size). These are combined in the API but do not necessarily need to be used as a single proof, unless this requirement can be calculated. The current hashing mechanism used is sha3 (keccak), this provides some requirement on the machine to "work" but is not ASIC resistant. This algorithm will likely be upgraded to something like [Equihash](https://www.internetsociety.org/sites/default/files/blogs-media/equihash-asymmetric-proof-of-work-based-generalized-birthday-problem.pdf) which will likely resist ASIC type workarounds, but importantly will allow better requirements on the memory requirements of a node (this is not measured in this crate yet). Disk space measurements may also be added in future. ## Analysis There is an example to test any values and allow measurements on different architectures. This can be run as ```cargo run --release --example analyse -- -h``` Which will allow users to play with settings for difficulty and size. Difficulty is the setting that asks the machine to continually push zeros to the beginning of any data until the number of leading bits of the hash of the data are zero. Similar to a common proof of work algorithm. The size parameter forces the nonce provided to be repeated until it reaches a certain size in bytes. This is then transferred back to the network as a proof. To find the proof the node must continually push a zero to the beginning of the data (not at the end as this is easily optimised). This forces the continuous reading of a large data segment in each hash iteration. Some figures on a desktop linux machine are below : Small data element (36 bytes) ``` cargo run --release -- -d 1 -s1024 -i Running analysis .... Difficulty = 1 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 1 Difficulty = 2 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 4 Difficulty = 3 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 4 Difficulty = 4 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 19 Difficulty = 5 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 85 Difficulty = 6 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 85 Difficulty = 7 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 85 Difficulty = 8 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 474 Difficulty = 9 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 474 Difficulty = 10 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 474 Difficulty = 11 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 1017 Difficulty = 12 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 1017 Difficulty = 13 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 4367 Difficulty = 14 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 4367 Difficulty = 15 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 4367 Difficulty = 16 size = 1024 create = 0 seconds check = 0 seconds num of attempts = 4367 Difficulty = 17 size = 1024 create = 155 seconds check = 0 seconds num of attempts = 248184 Difficulty = 18 size = 1024 create = 154 seconds check = 0 seconds num of attempts = 248184 Difficulty = 19 size = 1024 create = 1508 seconds check = 0 seconds num of attempts = 787761 Difficulty = 20 size = 1024 create = 6087 seconds check = 0 seconds num of attempts = 1587092 ``` Circa 100Mb data ``` cargo run --release -- -d=1 -s=102400000 -i Running analysis .... Difficulty = 1 size = 10485760 create = 0 seconds check = 0 seconds num of attempts = 0 Difficulty = 2 size = 10485760 create = 0 seconds check = 0 seconds num of attempts = 0 Difficulty = 3 size = 10485760 create = 0 seconds check = 0 seconds num of attempts = 0 Difficulty = 4 size = 10485760 create = 0 seconds check = 0 seconds num of attempts = 0 Difficulty = 5 size = 10485760 create = 3 seconds check = 0 seconds num of attempts = 61 Difficulty = 6 size = 10485760 create = 3 seconds check = 0 seconds num of attempts = 61 Difficulty = 7 size = 10485760 create = 3 seconds check = 0 seconds num of attempts = 61 Difficulty = 8 size = 10485760 create = 3 seconds check = 0 seconds num of attempts = 61 Difficulty = 9 size = 10485760 create = 25 seconds check = 0 seconds num of attempts = 478 Difficulty = 10 size = 10485760 create = 25 seconds check = 0 seconds num of attempts = 478 Difficulty = 11 size = 10485760 create = 66 seconds check = 0 seconds num of attempts = 1268 Difficulty = 12 size = 10485760 create = 210 seconds check = 0 seconds num of attempts = 4032 Difficulty = 13 size = 10485760 create = 755 seconds check = 0 seconds num of attempts = 14860 Difficulty = 14 size = 10485760 create = 1039 seconds check = 0 seconds num of attempts = 20484 Difficulty = 15 size = 10485760 create = 1035 seconds check = 0 seconds num of attempts = 20484 Difficulty = 16 size = 10485760 create = 1849 seconds check = 0 seconds num of attempts = 36453 Difficulty = 17 size = 10485760 create = 2594 seconds check = 0 seconds num of attempts = 51130 ``` The important point is that checking the proof is very fast and given enough difficulty, creating the proof is work intensive. This is a critical consideration that will mitigate some attack vectors on decentralised/p2p networks. It is by no means a security solution and should not be considered withouth continaul ongoing checks on a nodes "behaviour". ## License This SAFE Network library 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) http://opensource.org/licenses/MIT) at your option. ## Contribution Want to contribute? Great :tada: 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! For instructions on how to contribute, see our [Guide to contributing](https://github.com/maidsafe/QA/blob/master/CONTRIBUTING.md). resource_proof-1.0.39/codeowners000066400000000000000000000000371426135403300167340ustar00rootroot00000000000000* @maidsafe/backend_codeowners resource_proof-1.0.39/rustfmt.toml000066400000000000000000000000311426135403300172340ustar00rootroot00000000000000use_try_shorthand = true resource_proof-1.0.39/src/000077500000000000000000000000001426135403300154305ustar00rootroot00000000000000resource_proof-1.0.39/src/lib.rs000066400000000000000000000160751426135403300165550ustar00rootroot00000000000000// Copyright 2018 MaidSafe.net limited. // // 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, // modified, or distributed except according to those terms. Please review the Licences for the // specific language governing permissions and limitations relating to use of the SAFE Network // Software. //! # Resource proof //! //! A mechanism to test resource availability (CPU and bandwidth) of a machine prior to it joining //! a network. This crate provides the creation and validation algorithms. //! //! Validation has some CPU and memory requirements but far less than proof creation. Bandwidth //! tests (data transfer) affect the machine being proved and the machine doing validation equally; //! it is suggested that multiple machines test any new machine to apply an asymmetric load. //! //! [GitHub repository](https://github.com/maidsafe/resource_proof) #![doc( html_logo_url = "https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png", html_favicon_url = "https://maidsafe.net/img/favicon.ico", test(attr(forbid(warnings))) )] // For explanation of lint checks, run `rustc -W help` or see // https://github.com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md #![forbid( bad_style, arithmetic_overflow, mutable_transmutes, no_mangle_const_items, unknown_crate_types )] #![deny( deprecated, improper_ctypes, missing_docs, non_shorthand_field_patterns, overflowing_literals, stable_features, unconditional_recursion, unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes, unused_comparisons, unused_features, unused_parens, while_true, warnings )] #![warn( trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications, unused_results )] #![allow( box_pointers, missing_copy_implementations, missing_debug_implementations, variant_size_differences )] use std::collections::VecDeque; use tiny_keccak::{Hasher, Sha3}; /// Holds the prover requirements pub struct ResourceProof { min_size: usize, /// minimum size of proof in bytes difficulty: u8, } impl ResourceProof { /// Configure a new prover. /// /// `min_size` is target data size in bytes. It may be small or large to test bandwidth /// (although it may be compressible). /// /// `difficulty` is the number of leading binary zeros required in the hash. Each extra zero /// doubles the difficulty. pub fn new(min_size: usize, difficulty: u8) -> ResourceProof { ResourceProof { min_size, difficulty, } } /// Create the proof data with a given nonce. pub fn create_proof_data(&self, nonce: &[u8]) -> VecDeque { nonce.iter().cloned().cycle().take(self.min_size).collect() } /// Create a prover object. Requires a copy of the data (from `create_proof_data`) to be /// passed in. pub fn create_prover(&self, data: VecDeque) -> ResourceProver { ResourceProver { difficulty: self.difficulty, count: 0, data, } } /// Validate the proof data and key (this is the number of zeros to be pushed onto the data). pub fn validate_all(&self, nonce: &[u8], received_data: &VecDeque, key: u64) -> bool { let mut data = self.create_proof_data(nonce); if data != *received_data { return false; } for _ in 0..key { data.push_front(0u8); } self.check_hash(&data) >= self.difficulty } /// Validate the data for the given `nonce` and size data. pub fn validate_data(&self, nonce: &[u8], data: &VecDeque) -> bool { self.create_proof_data(nonce) == *data } /// Validate the proof key (this must recreate the data, hence `validate_all` is faster when /// both must be checked). pub fn validate_proof(&self, nonce: &[u8], key: u64) -> bool { let mut data = self.create_proof_data(nonce); for _ in 0..key { data.push_front(0u8); } self.check_hash(&data) >= self.difficulty } fn check_hash(&self, data: &VecDeque) -> u8 { ResourceProof::leading_zeros(&hash(&data.as_slices())) } fn leading_zeros(data: &[u8]) -> u8 { let mut zeros = 0u8; for (count, i) in data.iter().enumerate() { zeros = i.leading_zeros() as u8 + (count as u8 * 8); if i.leading_zeros() < 8 { break; } } zeros } } /// Object used to compute a result pub struct ResourceProver { difficulty: u8, count: u64, data: VecDeque, } impl ResourceProver { /// The expected number of steps is `pow(2, difficulty)`. /// The process is probabilistic, so the actual number of steps required may be more or less. /// /// The length of each step depends on data size. Total expected time is proportional to /// `length * pow(2, difficulty)`. pub fn expected_steps(&self) -> u64 { 2u64.pow(u32::from(self.difficulty)) } /// Try one step; if successful return the proof result. /// /// (This does not invalidate the prover. Continuing might find another valid solution.) pub fn try_step(&mut self) -> Option { if self.check_hash() >= self.difficulty { return Some(self.count); } self.data.push_front(0u8); self.count += 1; None } /// Keep stepping until a solution is found. Expected time can be calculated roughly (see /// `expected_steps`) but there is no upper bound (besides `u64::MAX`). pub fn solve(&mut self) -> u64 { loop { if let Some(solution) = self.try_step() { return solution; } } } fn check_hash(&self) -> u8 { ResourceProof::leading_zeros(&hash(&self.data.as_slices())) } } /// Hashes given seed into a nonce for use in proofs pub fn nonce_from_seed(seed: &[u8]) -> [u8; 32] { let mut hasher = Sha3::v256(); hasher.update(seed); let mut nonce = [0u8; 32]; hasher.finalize(&mut nonce); nonce } /// Simple wrapper around tiny-keccak for use with deques fn hash(data: &(&[u8], &[u8])) -> [u8; 32] { let mut hasher = Sha3::v256(); let mut res = [0u8; 32]; hasher.update(data.0); hasher.update(data.1); hasher.finalize(&mut res); res } #[cfg(test)] mod tests { use super::*; #[test] fn valid_proof() { for i in 0..20 { let nonce = nonce_from_seed(&[i]); let rp = ResourceProof::new(1024, 3); let data = rp.create_proof_data(&nonce); let proof = rp.create_prover(data.clone()).solve(); assert!(rp.validate_proof(&nonce, proof)); assert!(rp.validate_data(&nonce, &data)); assert!(rp.validate_all(&nonce, &data, proof)); } } } resource_proof-1.0.39/src/main.rs000066400000000000000000000101641426135403300167240ustar00rootroot00000000000000// Copyright 2018 MaidSafe.net limited. // // 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, // modified, or distributed except according to those terms. Please review the Licences for the // specific language governing permissions and limitations relating to use of the SAFE Network // Software. //! Command line tool for generating and validating resource proofs. // For explanation of lint checks, run `rustc -W help` or see // https://github.com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md #![forbid( arithmetic_overflow, mutable_transmutes, no_mangle_const_items, unknown_crate_types )] #![deny( deprecated, improper_ctypes, missing_docs, non_shorthand_field_patterns, overflowing_literals, stable_features, unconditional_recursion, unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes, unused_comparisons, unused_features, unused_parens, while_true, warnings )] #![warn( trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications, unused_results )] #![allow( box_pointers, missing_copy_implementations, missing_debug_implementations, variant_size_differences )] use clap::Parser; use resource_proof::ResourceProof; use std::time::Instant; #[cfg(not(windows))] use termion::color; fn test_it(dif: u8, size: usize, nonce: [u8; 32]) { let create = Instant::now(); let rp = ResourceProof::new(size, dif); let data = rp.create_proof_data(&nonce); let mut prover = rp.create_prover(data.clone()); let expected_steps = prover.expected_steps(); let proof = prover.solve(); let create_time = create.elapsed().as_secs(); let check = Instant::now(); if !rp.validate_proof(&nonce, proof) { println!("FAILED TO CONFIRM PROOF - POSSIBLE VIOLATION"); } if !rp.validate_data(&nonce, &data) { println!("FAILED TO CONFIRM PROOF DATA - POSSIBLE VIOLATION"); } if !rp.validate_all(&nonce, &data, proof) { println!("FAILED TO CONFIRM PROOF & DATA - POSSIBLE VIOLATION"); } println!( "Difficulty = {} expected_steps = {} size = {} create = {} seconds check = {} \ seconds num of steps = {:?}", dif, expected_steps, size, create_time, check.elapsed().as_secs(), proof ); } #[cfg(not(windows))] fn print_red(message: &str) { println!(); println!(); println!( "{}{}{}", color::Fg(color::Red), message, color::Fg(color::Reset) ); } #[cfg(windows)] fn print_red(message: &str) { println!(); println!(); println!("{}", message); } #[derive(Parser, Debug)] #[clap(author, version)] #[clap(name = "Simple Resource Proof example")] #[clap(about = "Please set the size and difficulty to test", long_about = None)] #[clap( after_help = "Several proofs may be chained, i.e. a large difficulty and small size or vice versa to check CPU And BW seperately" )] struct Config { #[clap(short, long)] #[clap(help = "The number of leading zeros of the proof when hashed with SHA3")] difficulty: u8, #[clap(short, long)] #[clap(help = "The minimum size of the proof in bytes")] size: usize, #[clap(long, default_value = "A long long time ago..")] #[clap(help = "Initial nonce seed")] seed: String, #[clap(short, long, action)] #[clap( help = "Will run continuously, increasing difficulty with every invocation. Note this will likley not stop in your lifetime :-)" )] increase: bool, } fn main() { let config = Config::parse(); print_red("Running analysis ...."); let nonce = resource_proof::nonce_from_seed(config.seed.as_bytes()); if config.increase { for i in config.difficulty.. { test_it(i, config.size, nonce); } } else { test_it(config.difficulty, config.size, nonce); } }