diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..233172d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9d042f7 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,81 @@ +name: Build + +on: + push: + branches: + - main + - release-* + pull_request: + branches: + - main + - release-* + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + env: + RUSTFLAGS: "--cfg async_executor_impl=\"async-std\" --cfg async_channel_impl=\"async-std\"" + RUST_LOG: info + steps: + - uses: styfle/cancel-workflow-action@0.12.0 + name: Cancel Outdated Builds + with: + all_but_latest: true + access_token: ${{ github.token }} + + - uses: actions/checkout@v4 + name: Checkout Repository + + - name: Install Protoc + uses: arduino/setup-protoc@v2 + + - uses: dtolnay/rust-toolchain@stable + + - name: Configure Git + run: | + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com".insteadOf git://github.com + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com".insteadOf ssh://git@github.com + + - uses: Swatinem/rust-cache@v2 + name: Enable Rust Caching + + - name: Format Check + run: cargo fmt -- --check + + # Run Clippy on all targets. The lint workflow doesn't run Clippy on tests, because the tests + # don't compile with all combinations of features. + - uses: actions-rs/clippy-check@v1 + name: Clippy + with: + token: ${{ github.token }} + args: --workspace --all-features --all-targets -- -D warnings + + - name: Audit + run: cargo audit --ignore RUSTSEC-2023-0018 --ignore RUSTSEC-2023-0052 --ignore RUSTSEC-2023-0065 + + - name: Build + # Build in release without `testing` feature, this should work without `hotshot_example` config. + run: | + cargo build --workspace --release + + - name: Test + # Build test binary with `testing` feature, which requires `hotshot_example` config + run: | + export RUSTFLAGS="$RUSTFLAGS --cfg hotshot_example" + cargo test --workspace --release --all-features --no-run + cargo test --workspace --release --all-features --verbose -- --test-threads 2 + timeout-minutes: 60 + + - name: Generate Documentation + run: | + cargo doc --no-deps --lib --release + echo '' > target/doc/index.html + + - name: Deploy Documentation + uses: peaceiris/actions-gh-pages@v3 + if: ${{ github.ref == 'refs/heads/main' }} + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./target/doc + cname: tide-disco.docs.espressosys.com diff --git a/.github/workflows/build_nix.yml b/.github/workflows/build_nix.yml new file mode 100644 index 0000000..8dcab5a --- /dev/null +++ b/.github/workflows/build_nix.yml @@ -0,0 +1,47 @@ +name: Nix + +on: + push: + branches: + - main + - release-* + schedule: + - cron: '0 0 * * 1' + workflow_dispatch: + +jobs: + nix: + runs-on: ubuntu-latest + timeout-minutes: 90 + steps: + - name: Configure Git + run: | + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com/".insteadOf git://github.com/ + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com/".insteadOf ssh://git@github.com/ + + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v24 + + # - uses: cachix/cachix-action@v12 + # with: + # name: espresso-systems-private + # authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + + - name: Cache cargo + uses: actions/cache@v3.3.2 + with: + path: | + ~/.cargo-nix/registry/index + ~/.cargo-nix/registry/cache + ~/.cargo-nix/git + target + key: espresso-nix-v2-${{ hashFiles('Cargo.lock') }} + + - name: "Sanity Check: nix environment loads" + run: nix-shell --run "echo Success" + + - name: "Sanity Check: nix environment builds all targets" + run: nix-shell --run "cargo build --all-targets --all-features --release --workspace" diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml new file mode 100644 index 0000000..acd52bc --- /dev/null +++ b/.github/workflows/build_windows.yml @@ -0,0 +1,57 @@ +# Copyright (c) 2022 Espresso Systems (espressosys.com) +# This file is part of the Tide Disco library. +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU +# General Public License as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# You should have received a copy of the GNU General Public License along with this program. If not, +# see . + +name: Windows build + +on: + push: + branches: + - main + - release-* + pull_request: + branches: + - main + - release-* + workflow_dispatch: + +jobs: + windows: + runs-on: windows-latest + env: + RUSTFLAGS: "--cfg async_executor_impl=\"async-std\" --cfg async_channel_impl=\"async-std\" --cfg hotshot_example" + RUST_LOG: info + steps: + - name: Configure Git + run: | + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com/".insteadOf git://github.com/ + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com/".insteadOf ssh://git@github.com/ + + - uses: dtolnay/rust-toolchain@stable + + - name: Install Protoc + uses: arduino/setup-protoc@v2 + + - name: Checkout Repository + uses: actions/checkout@v4 + + - uses: Swatinem/rust-cache@v2 + name: Enable Rust Caching + + - name: Build + run: | + cargo build --workspace --release + + - name: Test + run: | + cargo test --workspace --release --all-features --no-run + cargo test --workspace --release --all-features --verbose -- --test-threads 2 + timeout-minutes: 60 diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml new file mode 100644 index 0000000..6693abe --- /dev/null +++ b/.github/workflows/combine-prs.yml @@ -0,0 +1,24 @@ +name: Combine PRs + +on: + schedule: + - cron: "0 1 * * MON" + workflow_dispatch: # allows to manually trigger the workflow + +# The minimum permissions required to run this Action +permissions: + contents: write + pull-requests: write + checks: read + +jobs: + combine-prs: + runs-on: ubuntu-latest + + steps: + - name: combine-prs + id: combine-prs + uses: github/combine-prs@v5.0.0 + with: + github_token: ${{ secrets.ORG_GITHUB_PAT }} + labels: "dependabot,combined-pr" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..770257d --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,58 @@ +name: Code Coverage Workflow + +on: + push: + branches: + - main + - release-* + schedule: + - cron: "0 1 * * 1" + workflow_dispatch: + +jobs: + code-coverage: + runs-on: ubuntu-latest + timeout-minutes: 120 + steps: + - name: Configure Git + run: | + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com/".insteadOf git://github.com/ + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com/".insteadOf ssh://git@github.com/ + + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v24 + + - name: Enable Cachix + uses: cachix/cachix-action@v13 + # If PR is from a non-collaborator (e.g. dependabot) the secrets are missing and the login to cachix fails. + continue-on-error: true + with: + name: espresso-systems-private + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + extraPullNames: nix-community + skipPush: ${{ github.actor == 'dependabot[bot]' }} + + - name: Cache cargo + uses: actions/cache@v3.3.2 + with: + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git + target + key: hotshot-query-service-codecov-v1-${{ hashFiles('Cargo.lock') }} + + - name: Generate coverage reports + run: | + git config --global --add safe.directory "$PWD" + nix run "github:NixOS/nix?ref=1849e6a1f64734c488c2b1469249d65ce08cef93" -- develop .#perfShell -c cargo llvm-cov --profile=release --all-features --all-targets --lcov --output-path lcov.info -- --test-threads 1 + + - name: Coveralls upload + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: lcov.info + fail_ci_if_error: true diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml new file mode 100644 index 0000000..2e27082 --- /dev/null +++ b/.github/workflows/debug_build.yml @@ -0,0 +1,45 @@ +name: Debug Build + +on: + schedule: + - cron: "0 0 * * *" + +jobs: + build: + runs-on: ubuntu-latest + env: + RUSTFLAGS: "--cfg async_executor_impl=\"async-std\" --cfg async_channel_impl=\"async-std\"" + RUST_LOG: info + RUST_MIN_STACK: '3145728' + steps: + - name: Install Protoc + uses: arduino/setup-protoc@v2 + + - uses: dtolnay/rust-toolchain@stable + + - uses: styfle/cancel-workflow-action@0.12.0 + name: Cancel Outdated Builds + with: + all_but_latest: true + access_token: ${{ github.token }} + + - uses: actions/checkout@v4 + name: Checkout Repository + + - name: Configure Git + run: | + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com".insteadOf git://github.com + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com".insteadOf ssh://git@github.com + + - uses: Swatinem/rust-cache@v2 + name: Enable Rust Caching + + - name: Build + run: | + cargo build --workspace --all-features + + - name: Test + run: | + cargo test --workspace --all-features --no-run + cargo test --workspace --all-features --verbose -- --test-threads 2 + timeout-minutes: 60 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..27858f7 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,59 @@ +name: Lint + +on: + push: + branches: + - main + - release-* + pull_request: + branches: + - main + - release-* + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + strategy: + matrix: + # Lint with many combinations of feature flags + features: + # No optional features + - '' + # Each optional feature on its own + - sql-data-source + - file-system-data-source + - metrics-data-source + # All optional features together + - sql-data-source,file-system-data-source,metrics-data-source + env: + RUSTFLAGS: "--cfg async_executor_impl=\"async-std\" --cfg async_channel_impl=\"async-std\"" + RUST_LOG: info + steps: + - uses: styfle/cancel-workflow-action@0.12.0 + name: Cancel Outdated Builds + with: + all_but_latest: true + access_token: ${{ github.token }} + + - uses: actions/checkout@v4 + name: Checkout Repository + + - name: Install Protoc + uses: arduino/setup-protoc@v2 + + - uses: dtolnay/rust-toolchain@stable + + - name: Configure Git + run: | + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com".insteadOf git://github.com + git config --global url."https://ancient123:${{ secrets.ORG_GITHUB_PAT }}@github.com".insteadOf ssh://git@github.com + + - uses: Swatinem/rust-cache@v2 + name: Enable Rust Caching + + - uses: actions-rs/clippy-check@v1 + name: Clippy + with: + token: ${{ github.token }} + args: --workspace --no-default-features --features "${{ matrix.features }}" -- -D warnings diff --git a/.github/workflows/update_nix.yml b/.github/workflows/update_nix.yml new file mode 100644 index 0000000..8affd87 --- /dev/null +++ b/.github/workflows/update_nix.yml @@ -0,0 +1,26 @@ +name: update-flake-lock + +on: + workflow_dispatch: # allows manual triggering + schedule: + - cron: '0 0 * * 0' # runs weekly on Sunday at 00:00 + +jobs: + lockfile: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v24 + + - uses: cachix/cachix-action@v13 + with: + name: espresso-systems-private + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + + - name: Update flake.lock + uses: DeterminateSystems/update-flake-lock@v20 + with: + pr-title: "Weekly PR to bump flake.nix" # Title of PR to be created diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c1151d --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +**/target +**/result +**/out*.txt +**/out*.json +**/.idea +/*.pdf +**/target_dirs +/target_dirs +/.vscode/settings.json +**/.DS_Store diff --git a/.vscode/settings.json.example b/.vscode/settings.json.example new file mode 100644 index 0000000..f01b5af --- /dev/null +++ b/.vscode/settings.json.example @@ -0,0 +1,5 @@ +// Sets features for Rust Analyzer, since some features are required to be set for compilation +{ + "rust-analyzer.cargo.features": [ + ], +} diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4e861bb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "hs-builder-api" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1" +hotshot-types = { git = "https://github.com/EspressoSystems/HotShot.git", tag = "0.5.7.1" } +serde = { version = "1.0", features = ["derive"] } +sha2 = "0.10" + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9161d3 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# hs-builder-api +Minimal dependencies shared API definitions for HotShot Builder protocol diff --git a/api/builder.toml b/api/builder.toml new file mode 100644 index 0000000..7db1070 --- /dev/null +++ b/api/builder.toml @@ -0,0 +1,45 @@ +# Copyright (c) 2024 Espresso Systems (espressosys.com) +# This file is part of the HotShot Builder Protocol. +# +# TODO: License + +[meta] +NAME = "hs-builder" +DESCRIPTION = "" +FORMAT_VERSION = "0.1.0" + +[route.available_blocks] +PATH = ["availableblocks/:parent_hash"] +":parent_hash" = "TaggedBase64" +DOC = """ +Get descriptions for all block candidates based on a specific parent block. + +Returns +``` +[ + "block_metadata": { + "block_hash": TaggedBase64, + "block_size": integer, + "offered_fee": integer, + }, +] +``` +""" + +[route.claim_block] +PATH = ["claimblock/:block_hash/:signature"] +":block_hash" = "TaggedBase64" +":signature" = "TaggedBase64" +DOC = """ +Get the specified block candidate. + +Returns application-specific encoded transactions type +""" + +[route.submit_txn] +PATH = ["submittxn/:txn"] +":txn" = "TaggedBase64" +DOC = """ + +Returns --- +""" diff --git a/src/block_metadata.rs b/src/block_metadata.rs new file mode 100644 index 0000000..ee335de --- /dev/null +++ b/src/block_metadata.rs @@ -0,0 +1,17 @@ +use std::marker::PhantomData; + +use hotshot_types::traits::node_implementation::NodeType; +use serde::{Deserialize, Serialize}; +use sha2::digest::{generic_array::GenericArray, typenum}; + +pub type BlockHash = GenericArray; + +#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(bound = "")] +pub struct BlockMetadata { + block_hash: BlockHash, + block_size: u64, + offered_fee: u64, + _phantom: PhantomData, +} + diff --git a/src/data_source.rs b/src/data_source.rs new file mode 100644 index 0000000..11f35ae --- /dev/null +++ b/src/data_source.rs @@ -0,0 +1,13 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use hotshot_types::{data::VidCommitment, traits::{node_implementation::NodeType, signature_key::SignatureKey}}; + +use crate::block_metadata::{BlockHash, BlockMetadata}; + +#[async_trait] +pub trait BuilderDataSource { + async fn get_available_blocks(&self, for_parent: &VidCommitment) -> Vec>; + async fn claim_block(&self, block_hash: BlockHash, signature: <::SignatureKey as SignatureKey>::PureAssembledSignatureType) -> Arc>; + async fn submit_txn(&self, txn: ::Transaction); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..737f7bf --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +mod block_metadata; +mod data_source; +mod query_data; + diff --git a/src/query_data.rs b/src/query_data.rs new file mode 100644 index 0000000..b2bb9e9 --- /dev/null +++ b/src/query_data.rs @@ -0,0 +1,16 @@ +// Copyright (c) 2024 Espresso Systems (espressosys.com) +// This file is part of the HotShot HotShot Builder Protocol. +// +// TODO: License + + +use hotshot_types::traits::node_implementation::NodeType; +use serde::{Deserialize, Serialize}; + +use crate::block_metadata::BlockMetadata; + +#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(bound = "")] +pub struct AvailableBlocksQueryData { + pub blocks: Vec>, +}