diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..0da4573 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,6 @@ +[http] +timeout = 30 # timeout for each HTTP request, in seconds +multiplexing = false # HTTP/2 multiplexing + +[net] +retry = 50 # network retries diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 317f311..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: 2.1 - -orbs: - docker: circleci/docker@1.5.0 - -jobs: - Build: - docker: - - image: circleci/rust:latest - resource_class: xlarge - environment: - RUST_BACKTRACE: 1 - steps: - - checkout - - run: | - sudo bash .github/download_marine.sh - - restore_cache: - keys: - - trust-graph00-{{ checksum "./Cargo.lock" }} - - run: | - rustup target add wasm32-wasi - cargo test --no-fail-fast --release --all-features -- - cd ./service - ./build.sh - mkdir -p data - cargo test --no-fail-fast --release --all-features -- --test-threads=1 - - save_cache: - paths: - - ~/.cargo - - ~/.rustup - key: trust-graph00-{{ checksum "./Cargo.lock" }} - - -workflows: - version: 2 - CircleCI: - jobs: - - Build diff --git a/.github/download_marine.sh b/.github/download_marine.sh index c7609aa..c383f4f 100755 --- a/.github/download_marine.sh +++ b/.github/download_marine.sh @@ -3,7 +3,7 @@ set -o pipefail -o errexit -o nounset set -x MARINE_RELEASE="https://api.github.com/repos/fluencelabs/marine/releases/latest" -OUT_DIR=/usr/local/bin +OUT_DIR=~/.bin # get metadata about release curl -s -H "Accept: application/vnd.github.v3+json" $MARINE_RELEASE | diff --git a/.github/workflows/changelog_config.json b/.github/workflows/changelog_config.json index 9d01d64..a6cefa7 100644 --- a/.github/workflows/changelog_config.json +++ b/.github/workflows/changelog_config.json @@ -1,5 +1,6 @@ { - "template": "${{CHANGELOG}}\n\n${{UNCATEGORIZED}}", + "template": "## Changes since ${{FROM_TAG}}\n\n${{CHANGELOG}}\n\n${{UNCATEGORIZED}}", "pr_template": "- #${{NUMBER}} ${{TITLE}}", - "empty_template": "- no changes" + "empty_template": "## No changes since ${{FROM_TAG}}", + "sort": "DESC" } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 04ee8be..ff38319 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,9 +6,9 @@ on: - "v*" jobs: - npm-publish: + release: name: "Publish" - runs-on: ubuntu-latest + runs-on: builder container: rust defaults: run: @@ -30,36 +30,43 @@ jobs: - name: Download marine run: bash $GITHUB_WORKSPACE/.github/download_marine.sh + - uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' + - name: Cache npm uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-node-v01-${{ hashFiles('**/package-lock.json') }} + key: ${{ runner.os }}-node-v03-${{ hashFiles('**/package-lock.json') }} restore-keys: | - ${{ runner.os }}-node-v01- + ${{ runner.os }}-node-v03- - uses: actions/setup-node@v2 with: node-version: "15" registry-url: "https://registry.npmjs.org" - - uses: actions/cache@v2 + - name: Cache cargo + uses: actions/cache@v2 with: path: | ~/.cargo/registry ~/.cargo/git + ~/.cargo/bin key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly-2022-01-16 - target: wasm32-wasi - override: true + - name: Install Rust + working-directory: ./service + run: | + rustup toolchain install nightly-2022-01-16-x86_64-unknown-linux-gnu + rustup default nightly-2022-01-16-x86_64-unknown-linux-gnu + rustup override set nightly-2022-01-16-x86_64-unknown-linux-gnu + rustup target add wasm32-wasi --toolchain nightly-2022-01-16-x86_64-unknown-linux-gnu ### Build - - name: trust-graph.wasm + - name: Build trust-graph working-directory: ./service run: ./build.sh @@ -69,7 +76,7 @@ jobs: npm i npm run build - - name: Create builtin distribution package + - name: Create distribution package run: | ./builtin-package/package.sh @@ -81,15 +88,15 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -## Publish - - name: Release +### Publish + - name: Release to GitHub id: release uses: softprops/action-gh-release@v1 with: name: trust-graph ${{ env.RELEASE_VERSION }} tag_name: ${{ env.RELEASE_VERSION }} files: | - trust-graph.tar.gz + ./trust-graph.tar.gz body: ${{steps.changelog.outputs.changelog}} draft: false prerelease: false @@ -97,10 +104,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ### Publish Aqua API - - name: Publish Aqua API + ### Publish Aqua API + - name: Publish Aqua API to NPM run: | - npm version ${{ env.RELEASE_VERSION }} --allow-same-version + npm version ${{ env.RELEASE_VERSION }} npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -109,9 +116,9 @@ jobs: ## Update node-distro repo - name: Calculate SHA256 run: | - du -hs trust-graph.tar.gz - echo $(sha256sum trust-graph.tar.gz) - echo "SHA256=$(sha256sum trust-graph.tar.gz | awk '{ print $1 }')" >> $GITHUB_ENV + du -hs trust-graph.tar.gz + echo $(sha256sum trust-graph.tar.gz) + echo "SHA256=$(sha256sum trust-graph.tar.gz | awk '{ print $1 }')" >> $GITHUB_ENV - name: Get tar.gz URL id: package-url diff --git a/.github/workflows/rust_ci.yml b/.github/workflows/rust_ci.yml new file mode 100644 index 0000000..e2c31d9 --- /dev/null +++ b/.github/workflows/rust_ci.yml @@ -0,0 +1,89 @@ +name: Rust CI +on: + push: + workflow_dispatch: + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + check: + name: cargo nextest + runs-on: builder + container: rust + defaults: + run: + working-directory: service + shell: bash + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - run: mkdir -p ~/.bin + - run: echo "~/.bin" >> $GITHUB_PATH + + - name: Install Rust + working-directory: ./service + run: | + rustup toolchain install nightly-2022-01-16-x86_64-unknown-linux-gnu + rustup default nightly-2022-01-16-x86_64-unknown-linux-gnu + rustup override set nightly-2022-01-16-x86_64-unknown-linux-gnu + rustup target add wasm32-wasi --toolchain nightly-2022-01-16-x86_64-unknown-linux-gnu + + - name: Download jq + run: | + curl -L https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 -o ~/.bin/jq + chmod +x ~/.bin/jq + + - name: Download marine + run: bash $GITHUB_WORKSPACE/.github/download_marine.sh + + - name: Build + run: ./build.sh + + - run: cargo install --locked cargo-nextest --version 0.9.22 + - run: cargo nextest run --release --all-features --no-fail-fast --retries 10 --test-threads 10 + + lints: + name: Lints + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + components: rustfmt, clippy + + - name: Run cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + - name: Run cargo clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: -Z unstable-options --all + continue-on-error: true # do not fail for now diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index c0cb8c3..4f26d22 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -10,8 +10,16 @@ jobs: steps: - uses: actions/checkout@v2 + + - name: Get branch + run: | + BRANCH=${GITHUB_REF#refs/*/} + SANITIZED=$(echo "$BRANCH" | sed -e 's/[^a-zA-Z0-9-]/-/g') + echo "BRANCH=$SANITIZED" >> $GITHUB_ENV + - name: Bump version and push tag id: tag_version uses: mathieudutour/github-tag-action@v5.5 with: + append_to_pre_release_tag: ${{ env.BRANCH }} github_token: ${{ secrets.PERSONAL_TOKEN }} diff --git a/keypair/src/public_key.rs b/keypair/src/public_key.rs index 7271b2e..7da3917 100644 --- a/keypair/src/public_key.rs +++ b/keypair/src/public_key.rs @@ -165,7 +165,7 @@ impl TryFrom for PublicKey { fn try_from(peer_id: libp2p_core::PeerId) -> Result { Ok(as_public_key(&peer_id) - .ok_or(DecodingError::PublicKeyNotInlined(peer_id.to_base58()))? + .ok_or_else(|| DecodingError::PublicKeyNotInlined(peer_id.to_base58()))? .into()) } } @@ -177,7 +177,9 @@ fn as_public_key(peer_id: &PeerId) -> Option { let mhash = peer_id.as_ref(); match multihash::Code::try_from(mhash.code()) { - Ok(multihash::Code::Identity) => libp2p_core::PublicKey::from_protobuf_encoding(mhash.digest()).ok(), + Ok(multihash::Code::Identity) => { + libp2p_core::PublicKey::from_protobuf_encoding(mhash.digest()).ok() + } _ => None, } } diff --git a/service/src/dto.rs b/service/src/dto.rs index df48e3c..4f2a8eb 100644 --- a/service/src/dto.rs +++ b/service/src/dto.rs @@ -40,7 +40,7 @@ pub struct Certificate { impl From for Certificate { fn from(c: trust_graph::Certificate) -> Self { let chain: Vec = c.chain.into_iter().map(|t| t.into()).collect(); - return Certificate { chain }; + Certificate { chain } } } @@ -51,10 +51,10 @@ impl TryFrom for trust_graph::Certificate { let chain: Result, DtoConversionError> = c .chain .into_iter() - .map(|t| trust_graph::Trust::try_from(t)) + .map(trust_graph::Trust::try_from) .collect(); let chain = chain?; - return Ok(trust_graph::Certificate { chain }); + Ok(trust_graph::Certificate { chain }) } } @@ -85,12 +85,12 @@ impl TryFrom for trust_graph::Trust { let signature = Signature::from_bytes(KeyFormat::from_str(&t.sig_type)?, signature); let expires_at = Duration::from_secs(t.expires_at); let issued_at = Duration::from_secs(t.issued_at); - return Ok(trust_graph::Trust { + Ok(trust_graph::Trust { issued_for, expires_at, signature, issued_at, - }); + }) } } @@ -101,13 +101,13 @@ impl From for Trust { let signature = bs58::encode(raw_signature.bytes).into_string(); let expires_at = t.expires_at.as_secs(); let issued_at = t.issued_at.as_secs(); - return Trust { + Trust { issued_for, expires_at, signature, sig_type: raw_signature.sig_type.into(), issued_at, - }; + } } } @@ -142,12 +142,12 @@ impl TryFrom for trust_graph::Revocation { let signature = bs58::decode(&r.signature).into_vec()?; let signature = Signature::from_bytes(KeyFormat::from_str(&r.sig_type)?, signature); let revoked_at = Duration::from_secs(r.revoked_at); - return Ok(trust_graph::Revocation { + Ok(trust_graph::Revocation { pk: revoked_pk, revoked_at, revoked_by: revoked_by_pk, signature, - }); + }) } } @@ -158,12 +158,12 @@ impl From for Revocation { let raw_signature = r.signature.get_raw_signature(); let signature = bs58::encode(raw_signature.bytes).into_string(); let revoked_at = r.revoked_at.as_secs(); - return Revocation { + Revocation { revoked_peer_id, revoked_at, signature, sig_type: raw_signature.sig_type.into(), revoked_by, - }; + } } } diff --git a/service/src/main.rs b/service/src/main.rs index cdce3e8..feaeed8 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -14,15 +14,15 @@ mod service_api; mod storage_impl; mod tests; /* - _initialize function that calls __wasm_call_ctors is required to mitigade memory leak - that is described in https://github.com/WebAssembly/wasi-libc/issues/298 + _initialize function that calls __wasm_call_ctors is required to mitigade memory leak + that is described in https://github.com/WebAssembly/wasi-libc/issues/298 - In short, without this code rust wraps every export function - with __wasm_call_ctors/__wasm_call_dtors calls. This causes memory leaks. When compiler sees - an explicit call to __wasm_call_ctors in _initialize function, it disables export wrapping. + In short, without this code rust wraps every export function + with __wasm_call_ctors/__wasm_call_dtors calls. This causes memory leaks. When compiler sees + an explicit call to __wasm_call_ctors in _initialize function, it disables export wrapping. - TODO: remove when updating to marine-rs-sdk with fix - */ + TODO: remove when updating to marine-rs-sdk with fix +*/ extern "C" { pub fn __wasm_call_ctors(); } diff --git a/service/src/service_api.rs b/service/src/service_api.rs index bbb10f6..6928f1d 100644 --- a/service/src/service_api.rs +++ b/service/src/service_api.rs @@ -27,10 +27,10 @@ fn set_root(peer_id: String, max_chain_len: u32) -> SetRootResult { }) .into() } else { - return SetRootResult { + SetRootResult { success: false, error: ServiceError::NotOwner.to_string(), - }; + } } } diff --git a/service/src/storage_impl.rs b/service/src/storage_impl.rs index 8d7dab7..7636474 100644 --- a/service/src/storage_impl.rs +++ b/service/src/storage_impl.rs @@ -272,7 +272,7 @@ impl Storage for SQLiteStorage { statement.bind(6, &Value::Binary(relation.signature().encode()))?; statement.next()?; - Ok({}) + Ok(()) } fn get_root_weight_factor(&self, pk: &PK) -> Result, Self::Error> { @@ -309,7 +309,7 @@ impl Storage for SQLiteStorage { ])?; cursor.next()?; - Ok({}) + Ok(()) } fn root_keys(&self) -> Result, Self::Error> { diff --git a/src/certificate.rs b/src/certificate.rs index cea1290..edf856b 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -74,14 +74,26 @@ impl Certificate { Self { chain } } - pub fn new_from_root_trust(root_trust: Trust, issued_trust: Trust, cur_time: Duration) -> Result { + pub fn new_from_root_trust( + root_trust: Trust, + issued_trust: Trust, + cur_time: Duration, + ) -> Result { Trust::verify(&root_trust, &root_trust.issued_for, cur_time).map_err(MalformedRoot)?; - Trust::verify(&issued_trust, &root_trust.issued_for, cur_time).map_err(|e| VerificationError(1, e))?; + Trust::verify(&issued_trust, &root_trust.issued_for, cur_time) + .map_err(|e| VerificationError(1, e))?; - Ok(Self { chain: vec![root_trust, issued_trust] }) + Ok(Self { + chain: vec![root_trust, issued_trust], + }) } - pub fn issue_with_trust(issued_by: PublicKey, trust: Trust, extend_cert: &Certificate, cur_time: Duration) -> Result { + pub fn issue_with_trust( + issued_by: PublicKey, + trust: Trust, + extend_cert: &Certificate, + cur_time: Duration, + ) -> Result { if trust.expires_at.lt(&trust.issued_at) { return Err(ExpirationError { expires_at: format!("{:?}", trust.expires_at), @@ -89,7 +101,11 @@ impl Certificate { }); } - Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?; + Certificate::verify( + extend_cert, + &[extend_cert.chain[0].issued_for.clone()], + cur_time, + )?; // check if `issued_by` is allowed to issue a certificate (i.e., there’s a trust for it in a chain) let mut previous_trust_num: i32 = -1; for pk_id in 0..extend_cert.chain.len() { @@ -114,7 +130,6 @@ impl Certificate { Ok(Self { chain: new_chain }) } - /// Creates new certificate with root trust (self-signed public key) from a key pair. #[allow(dead_code)] pub fn issue_root( @@ -151,7 +166,11 @@ impl Certificate { } // first, verify given certificate - Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?; + Certificate::verify( + extend_cert, + &[extend_cert.chain[0].issued_for.clone()], + cur_time, + )?; let issued_by_pk = issued_by.public(); @@ -309,7 +328,7 @@ impl FromStr for Certificate { str_lines[i + 2], str_lines[i + 3], ) - .map_err(|e| DecodeTrustError(i, e))?; + .map_err(|e| DecodeTrustError(i, e))?; trusts.push(trust); } @@ -353,7 +372,7 @@ mod tests { cur_time, cur_time, ) - .unwrap(); + .unwrap(); let serialized = new_cert.to_string(); let deserialized = Certificate::from_str(&serialized); @@ -380,7 +399,7 @@ mod tests { cur_time, cur_time, ) - .unwrap(); + .unwrap(); let serialized = new_cert.encode(); let deserialized = Certificate::decode(serialized.as_slice()); @@ -468,7 +487,7 @@ mod tests { cur_time.checked_sub(one_minute()).unwrap(), cur_time, ) - .unwrap(); + .unwrap(); assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_err()); } @@ -490,7 +509,7 @@ mod tests { cur_time, cur_time, ) - .unwrap(); + .unwrap(); let new_cert = Certificate::issue( &third_kp, fourth_kp.public(), @@ -528,7 +547,7 @@ mod tests { cur_time, cur_time, ) - .unwrap(); + .unwrap(); let new_cert = Certificate::issue( &second_kp, fourth_kp.public(), diff --git a/src/trust_graph.rs b/src/trust_graph.rs index 3f07034..5f7a8b5 100644 --- a/src/trust_graph.rs +++ b/src/trust_graph.rs @@ -95,7 +95,7 @@ impl From for String { } fn get_weight_factor(max_chain_len: u32) -> u32 { - MAX_WEIGHT_FACTOR.checked_sub(max_chain_len).unwrap_or(0u32) + MAX_WEIGHT_FACTOR.saturating_sub(max_chain_len) } pub fn get_weight_from_factor(wf: WeightFactor) -> u32 {