From 9979a63dcea1223dc1226b72839db96d70d344b2 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Mon, 23 Sep 2024 16:56:11 +1000 Subject: [PATCH] Add basic repository structure (#2) --- .dockerignore | 3 + .editorconfig | 9 ++ .github/ISSUE_TEMPLATE.md | 21 +++ .github/PULL_REQUEST_TEMPLATE.md | 12 ++ .github/custom/config.toml | 3 + .github/workflows/book.yml | 35 +++++ .github/workflows/docker.yml | 163 ++++++++++++++++++++ .github/workflows/linkcheck.yml | 37 +++++ .github/workflows/release.yml | 251 +++++++++++++++++++++++++++++++ .github/workflows/test-suite.yml | 210 ++++++++++++++++++++++++++ CONTRIBUTING.md | 127 ++++++++++++++++ Cargo.toml | 3 +- Makefile | 151 +++++++++++++++++++ README.md | 32 +++- SECURITY.md | 13 ++ book/src/SUMMARY.md | 2 + book/src/contributing.md | 111 ++++++++++++++ book/src/setup.md | 44 ++++++ scripts/cli.sh | 79 ++++++++++ scripts/mdlint.sh | 23 +++ 20 files changed, 1327 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/custom/config.toml create mode 100644 .github/workflows/book.yml create mode 100644 .github/workflows/docker.yml create mode 100644 .github/workflows/linkcheck.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test-suite.yml create mode 100644 CONTRIBUTING.md create mode 100644 Makefile create mode 100644 SECURITY.md create mode 100644 book/src/contributing.md create mode 100644 book/src/setup.md create mode 100755 scripts/cli.sh create mode 100755 scripts/mdlint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..76062bb9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +target/ +*.data +*.tar.gz diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..149415d1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true +[*] +indent_style=space +indent_size=4 +end_of_line=lf +charset=utf-8 +trim_trailing_whitespace=true +max_line_length=100 +insert_final_newline=true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..e1561fce --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,21 @@ +## Description + +Please provide a brief description of the issue. + +## Version + +Please provide your SSV version and Rust version. Are you building from +`stable` or `unstable`, which commit? + +## Present Behaviour + +Describe the present behaviour of the application, with regards to this +issue. + +## Expected Behaviour + +How _should_ the application behave? + +## Steps to resolve + +Please describe the steps required to resolve this issue, if known. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..01ca90a7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ +## Issue Addressed + +Which issue # does this PR address? + +## Proposed Changes + +Please list or describe the changes introduced by this PR. + +## Additional Info + +Please provide any additional information. For example, future considerations +or information useful for reviewers. diff --git a/.github/custom/config.toml b/.github/custom/config.toml new file mode 100644 index 00000000..283d6e20 --- /dev/null +++ b/.github/custom/config.toml @@ -0,0 +1,3 @@ +# Custom Cargo config to be used for the udeps CI job +[http] +multiplexing = false diff --git a/.github/workflows/book.yml b/.github/workflows/book.yml new file mode 100644 index 00000000..d2eacbf3 --- /dev/null +++ b/.github/workflows/book.yml @@ -0,0 +1,35 @@ +# TODO: Setup markdown book +# name: mdbook +# +# on: +# push: +# branches: +# - unstable +# +# concurrency: +# group: ${{ github.workflow }}-${{ github.ref }} +# cancel-in-progress: true +# +# jobs: +# build-and-upload-to-s3: +# runs-on: ubuntu-20.04 +# steps: +# - uses: actions/checkout@v4 +# +# - name: Setup mdBook +# uses: peaceiris/actions-mdbook@v1 +# with: +# mdbook-version: 'latest' +# +# - run: mdbook build +# working-directory: book +# +# - uses: jakejarvis/s3-sync-action@be0c4ab89158cac4278689ebedd8407dd5f35a83 +# with: +# args: --follow-symlinks --delete +# env: +# AWS_S3_BUCKET: ${{ secrets.AWS_S3_BOOK_BUCKET }} +# AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} +# AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} +# AWS_REGION: 'ap-southeast-2' +# SOURCE_DIR: 'book/book' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..ca29ce74 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,163 @@ +# TODO: Setup docker +# name: docker +# +# on: +# push: +# branches: +# - stable +# tags: +# - v* +# +# concurrency: +# group: ${{ github.workflow }}-${{ github.ref }} +# cancel-in-progress: true +# +# env: +# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} +# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} +# # Enable self-hosted runners for the sigp repo only. +# SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/ssv' }} +# +# jobs: +# # Extract the VERSION which is either `latest` or `vX.Y.Z`, and the VERSION_SUFFIX +# # which is either empty or `-unstable`. +# # +# # It would be nice if the arch didn't get spliced into the version between `latest` and +# # `unstable`, but for now we keep the two parts of the version separate for backwards +# # compatibility. +# extract-version: +# runs-on: ubuntu-22.04 +# steps: +# - name: Extract version (if stable) +# if: github.event.ref == 'refs/heads/stable' +# run: | +# echo "VERSION=latest" >> $GITHUB_ENV +# echo "VERSION_SUFFIX=" >> $GITHUB_ENV +# - name: Extract version (if unstable) +# if: github.event.ref == 'refs/heads/unstable' +# run: | +# echo "VERSION=latest" >> $GITHUB_ENV +# echo "VERSION_SUFFIX=-unstable" >> $GITHUB_ENV +# - name: Extract version (if tagged release) +# if: startsWith(github.event.ref, 'refs/tags') +# run: | +# echo "VERSION=$(echo ${GITHUB_REF#refs/tags/})" >> $GITHUB_ENV +# echo "VERSION_SUFFIX=" >> $GITHUB_ENV +# outputs: +# VERSION: ${{ env.VERSION }} +# VERSION_SUFFIX: ${{ env.VERSION_SUFFIX }} +# build-docker-single-arch: +# name: build-docker-${{ matrix.binary }}-${{ matrix.cpu_arch }}${{ matrix.features.version_suffix }} +# # Use self-hosted runners only on the sigp repo. +# runs-on: ${{ github.repository == 'sigp/ssv' && fromJson('["self-hosted", "linux", "release"]') || 'ubuntu-22.04' }} +# strategy: +# matrix: +# binary: [ssv] +# cpu_arch: [aarch64, x86_64] +# include: +# - profile: maxperf +# +# needs: [extract-version] +# env: +# VERSION: ${{ needs.extract-version.outputs.VERSION }} +# VERSION_SUFFIX: ${{ needs.extract-version.outputs.VERSION_SUFFIX }} +# steps: +# - uses: actions/checkout@v4 +# - name: Update Rust +# if: env.SELF_HOSTED_RUNNERS == 'false' +# run: rustup update stable +# - name: Dockerhub login +# run: | +# echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin +# +# - name: Sets env vars for SSV +# if: startsWith(matrix.binary, 'lighthouse') +# run: | +# echo "CROSS_FEATURES=gnosis,spec-minimal,slasher-lmdb,jemalloc" >> $GITHUB_ENV +# +# - name: Set `make` command for lighthouse +# if: startsWith(matrix.binary, 'lighthouse') +# run: | +# echo "MAKE_CMD=build-${{ matrix.cpu_arch }}" >> $GITHUB_ENV +# +# - name: Set `make` command for lcli +# if: startsWith(matrix.binary, 'lcli') +# run: | +# echo "MAKE_CMD=build-lcli-${{ matrix.cpu_arch }}" >> $GITHUB_ENV +# +# - name: Cross build binaries +# run: | +# cargo install cross +# env CROSS_PROFILE=${{ matrix.profile }} CROSS_FEATURES=${{ env.CROSS_FEATURES }} make ${{ env.MAKE_CMD }} +# +# - name: Make bin dir +# run: mkdir ./bin +# +# - name: Move cross-built binary into Docker scope +# run: mv ./target/${{ matrix.cpu_arch }}-unknown-linux-gnu/${{ matrix.profile }}/${{ matrix.binary }} ./bin +# +# - name: Map aarch64 to arm64 short arch +# if: startsWith(matrix.cpu_arch, 'aarch64') +# run: echo "SHORT_ARCH=arm64" >> $GITHUB_ENV +# +# - name: Map x86_64 to amd64 short arch +# if: startsWith(matrix.cpu_arch, 'x86_64') +# run: echo "SHORT_ARCH=amd64" >> $GITHUB_ENV; +# +# - name: Install QEMU +# if: env.SELF_HOSTED_RUNNERS == 'false' +# run: sudo apt-get update && sudo apt-get install -y qemu-user-static +# +# - name: Set up Docker Buildx +# if: env.SELF_HOSTED_RUNNERS == 'false' +# uses: docker/setup-buildx-action@v3 +# +# - name: Build and push (Lighthouse) +# if: startsWith(matrix.binary, 'lighthouse') +# uses: docker/build-push-action@v5 +# with: +# file: ./Dockerfile.cross +# context: . +# platforms: linux/${{ env.SHORT_ARCH }} +# push: true +# tags: | +# ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }} +# +# - name: Build and push (lcli) +# if: startsWith(matrix.binary, 'lcli') +# uses: docker/build-push-action@v5 +# with: +# file: ./lcli/Dockerfile.cross +# context: . +# platforms: linux/${{ env.SHORT_ARCH }} +# push: true +# +# tags: | +# ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }} +# +# +# build-docker-multiarch: +# name: build-docker-${{ matrix.binary }}-multiarch +# runs-on: ubuntu-22.04 +# strategy: +# matrix: +# binary: [lighthouse, +# lcli] +# needs: [build-docker-single-arch, extract-version] +# env: +# VERSION: ${{ needs.extract-version.outputs.VERSION }} +# VERSION_SUFFIX: ${{ needs.extract-version.outputs.VERSION_SUFFIX }} +# steps: +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@v3 +# +# - name: Dockerhub login +# run: | +# echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin +# +# - name: Create and push multiarch manifests +# run: | +# docker buildx imagetools create -t ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}${VERSION_SUFFIX} \ +# ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-arm64${VERSION_SUFFIX} \ +# ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-amd64${VERSION_SUFFIX}; +# diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml new file mode 100644 index 00000000..5ceca2e6 --- /dev/null +++ b/.github/workflows/linkcheck.yml @@ -0,0 +1,37 @@ +# TODO: Setup mdbook +# name: linkcheck +# +# on: +# push: +# branches: +# - unstable +# pull_request: +# paths: +# - 'book/**' +# merge_group: +# +# concurrency: +# group: ${{ github.workflow }}-${{ github.ref }} +# cancel-in-progress: true +# +# jobs: +# linkcheck: +# name: Check broken links +# runs-on: ubuntu-latest +# +# steps: +# - name: Checkout code +# uses: actions/checkout@v4 +# +# - name: Run mdbook server +# run: | +# docker run -v ${{ github.workspace }}/book:/book --name book -p 3000:3000 -d peaceiris/mdbook:latest serve --hostname 0.0.0.0 +# sleep 5 +# +# - name: Print logs +# run: docker logs book +# +# - name: Run linkcheck +# run: | +# curl -sL https://github.com/filiph/linkcheck/releases/download/3.0.0/linkcheck-3.0.0-linux-x64.tar.gz | tar xvzf - linkcheck/linkcheck --strip 1 +# ./linkcheck localhost:3000 -d diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..3bf8e6da --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,251 @@ +# TODO: Setup release pipeline +# name: Release Suite +# +# on: +# push: +# tags: +# - v* +# +# concurrency: +# group: ${{ github.workflow }}-${{ github.ref }} +# cancel-in-progress: true +# +# env: +# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} +# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} +# REPO_NAME: ${{ github.repository_owner }}/lighthouse +# IMAGE_NAME: ${{ github.repository_owner }}/lighthouse +# # Enable self-hosted runners for the sigp repo only. +# SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/lighthouse' }} +# +# jobs: +# extract-version: +# runs-on: ubuntu-latest +# steps: +# - name: Extract version +# run: echo "VERSION=$(echo ${GITHUB_REF#refs/tags/})" >> $GITHUB_OUTPUT +# id: extract_version +# outputs: +# VERSION: ${{ steps.extract_version.outputs.VERSION }} +# build: +# name: Build Release +# strategy: +# matrix: +# arch: [aarch64-unknown-linux-gnu, +# x86_64-unknown-linux-gnu, +# x86_64-apple-darwin, +# x86_64-windows] +# include: +# - arch: aarch64-unknown-linux-gnu +# runner: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "release", "large"]') || 'ubuntu-latest' }} +# profile: maxperf +# - arch: x86_64-unknown-linux-gnu +# runner: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "release", "large"]') || 'ubuntu-latest' }} +# profile: maxperf +# - arch: x86_64-apple-darwin +# runner: macos-13 +# profile: maxperf +# - arch: x86_64-windows +# runner: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "windows", "release"]') || 'windows-2019' }} +# profile: maxperf +# +# runs-on: ${{ matrix.runner }} +# needs: extract-version +# steps: +# - name: Checkout sources +# uses: actions/checkout@v4 +# - name: Get latest version of stable Rust +# if: env.SELF_HOSTED_RUNNERS == 'false' +# run: rustup update stable +# +# # ============================== +# # Windows dependencies +# # ============================== +# +# - uses: KyleMayes/install-llvm-action@v1 +# if: env.SELF_HOSTED_RUNNERS == 'false' && startsWith(matrix.arch, 'x86_64-windows') +# with: +# version: "17.0" +# directory: ${{ runner.temp }}/llvm +# - name: Set LIBCLANG_PATH +# if: startsWith(matrix.arch, 'x86_64-windows') +# run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV +# +# # ============================== +# # Builds +# # ============================== +# +# - name: Build Lighthouse for aarch64-unknown-linux-gnu +# if: matrix.arch == 'aarch64-unknown-linux-gnu' +# run: | +# cargo install cross +# env CROSS_PROFILE=${{ matrix.profile }} make build-aarch64 +# +# - name: Build Lighthouse for x86_64-unknown-linux-gnu +# if: matrix.arch == 'x86_64-unknown-linux-gnu' +# run: | +# cargo install cross +# env CROSS_PROFILE=${{ matrix.profile }} make build-x86_64 +# +# - name: Move cross-compiled binary +# if: contains(matrix.arch, 'unknown-linux-gnu') +# run: mv target/${{ matrix.arch }}/${{ matrix.profile }}/lighthouse ~/.cargo/bin/lighthouse +# +# - name: Build Lighthouse for x86_64-apple-darwin +# if: matrix.arch == 'x86_64-apple-darwin' +# run: cargo install --path lighthouse --force --locked --features portable,gnosis --profile ${{ matrix.profile }} +# +# - name: Build Lighthouse for Windows +# if: matrix.arch == 'x86_64-windows' +# run: cargo install --path lighthouse --force --locked --features portable,gnosis --profile ${{ matrix.profile }} +# +# - name: Configure GPG and create artifacts +# if: startsWith(matrix.arch, 'x86_64-windows') != true +# env: +# GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} +# GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} +# run: | +# export GPG_TTY=$(tty) +# echo "$GPG_SIGNING_KEY" | gpg --batch --import +# mkdir artifacts +# mv ~/.cargo/bin/lighthouse ./artifacts +# cd artifacts +# tar -czf lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz lighthouse +# echo "$GPG_PASSPHRASE" | gpg --passphrase-fd 0 --pinentry-mode loopback --batch -ab lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz +# for ext in "tar.gz" "tar.gz.asc";\ +# do for f in *.$ext;\ +# do cp $f "../${f%.$ext}.$ext";\ +# done;\ +# done +# mv *tar.gz* .. +# +# - name: Configure GPG and create artifacts Windows +# if: startsWith(matrix.arch, 'x86_64-windows') +# env: +# GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} +# GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} +# run: | +# echo $env:GPG_SIGNING_KEY | gpg --batch --import +# mkdir artifacts +# move $env:USERPROFILE/.cargo/bin/lighthouse.exe ./artifacts +# cd artifacts +# tar -czf lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz lighthouse.exe +# gpg --passphrase "$env:GPG_PASSPHRASE" --batch --pinentry-mode loopback -ab lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz +# move *tar.gz* .. +# +# # ======================================================================= +# # Upload artifacts +# # This is required to share artifacts between different jobs +# # ======================================================================= +# +# - name: Upload artifact +# uses: actions/upload-artifact@v4 +# with: +# name: lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz +# path: lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz +# compression-level: 0 +# +# - name: Upload signature +# uses: actions/upload-artifact@v4 +# with: +# name: lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz.asc +# path: lighthouse-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.arch }}.tar.gz.asc +# compression-level: 0 +# +# draft-release: +# name: Draft Release +# needs: [build, extract-version] +# runs-on: ubuntu-latest +# env: +# VERSION: ${{ needs.extract-version.outputs.VERSION }} +# steps: +# # This is necessary for generating the changelog. It has to come before "Download Artifacts" or else it deletes the artifacts. +# - name: Checkout sources +# uses: actions/checkout@v4 +# with: +# fetch-depth: 0 +# +# # ============================== +# # Download artifacts +# # ============================== +# +# - name: Download artifacts +# uses: actions/download-artifact@v4 +# +# # ============================== +# # Create release draft +# # ============================== +# +# - name: Generate Full Changelog +# id: changelog +# run: | +# echo "CHANGELOG<> $GITHUB_OUTPUT +# echo "$(git log --pretty=format:"- %s" $(git describe --tags --abbrev=0 ${{ env.VERSION }}^)..${{ env.VERSION }})" >> $GITHUB_OUTPUT +# echo "EOF" >> $GITHUB_OUTPUT +# +# - name: Create Release Draft +# env: +# GITHUB_USER: ${{ github.repository_owner }} +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# +# # The formatting here is borrowed from OpenEthereum: https://github.com/openethereum/openethereum/blob/main/.github/workflows/build.yml +# run: | +# body=$(cat <<- "ENDBODY" +# +# +# ## Testing Checklist (DELETE ME) +# +# - [ ] Run on synced Holesky Sigma Prime nodes. +# - [ ] Run on synced Canary (mainnet) Sigma Prime nodes. +# - [ ] Resync a Holesky node. +# - [ ] Resync a mainnet node. +# +# ## Release Checklist (DELETE ME) +# +# - [ ] Merge `unstable` -> `stable`. +# - [ ] Ensure docker images are published (check `latest` and the version tag). +# - [ ] Prepare Discord post. +# - [ ] Prepare Twitter post. +# - [ ] Prepare mailing list email. +# +# ## Summary +# +# Add a summary. +# +# ## Update Priority +# +# This table provides priorities for which classes of users should update particular components. +# +# |User Class |Beacon Node | Validator Client| +# --- | --- | --- +# |Staking Users| | | +# |Non-Staking Users| |---| +# +# *See [Update +# Priorities](https://lighthouse-book.sigmaprime.io/installation-priorities.html) +# more information about this table.* +# +# ## All Changes +# +# ${{ steps.changelog.outputs.CHANGELOG }} +# +# ## Binaries +# +# [See pre-built binaries documentation.](https://lighthouse-book.sigmaprime.io/installation-binaries.html) +# +# The binaries are signed with Sigma Prime's PGP key: `15E66D941F697E28F49381F426416DC3F30674B0` +# +# | System | Architecture | Binary | PGP Signature | +# |:---:|:---:|:---:|:---| +# | | x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz.asc) | +# | | x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz.asc) | +# | | aarch64 | [lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz.asc) | +# | | x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz.asc) | +# | | | | | +# | **System** | **Option** | - | **Resource** | +# | | Docker | [${{ env.VERSION }}](https://hub.docker.com/r/${{ env.IMAGE_NAME }}/tags?page=1&ordering=last_updated&name=${{ env.VERSION }}) | [${{ env.IMAGE_NAME }}](https://hub.docker.com/r/${{ env.IMAGE_NAME }}) | +# ENDBODY +# ) +# assets=(./lighthouse-*.tar.gz*/lighthouse-*.tar.gz*) +# tag_name="${{ env.VERSION }}" +# echo "$body" | gh release create --draft -F "-" "$tag_name" "${assets[@]}" diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml new file mode 100644 index 00000000..923a12e9 --- /dev/null +++ b/.github/workflows/test-suite.yml @@ -0,0 +1,210 @@ +name: test-suite + +on: + push: + branches: + - stable + - 'pr/*' + pull_request: + merge_group: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # Deny warnings in CI + # Disable debug info (see https://github.com/sigp/lighthouse/issues/4005) + RUSTFLAGS: "-D warnings -C debuginfo=0" + # Prevent Github API rate limiting. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Enable self-hosted runners for the sigp repo only. + SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/ssv' }} + # Self-hosted runners need to reference a different host for `./watch` tests. + WATCH_HOST: ${{ github.repository == 'sigp/ssv' && 'host.docker.internal' || 'localhost' }} + # Disable incremental compilation + CARGO_INCREMENTAL: 0 + # Enable portable to prevent issues with caching `blst` for the wrong CPU type + # TEST_FEATURES: portable +jobs: + check-labels: + runs-on: ubuntu-latest + name: Check for 'skip-ci' label + outputs: + skip_ci: ${{ steps.set-output.outputs.SKIP_CI }} + steps: + - name: check for skip-ci label + id: set-output + env: + LABELS: ${{ toJson(github.event.pull_request.labels) }} + run: | + SKIP_CI="false" + if [ -z "${LABELS}" ] || [ "${LABELS}" = "null" ]; then + LABELS="none"; + else + LABELS=$(echo ${LABELS} | jq -r '.[].name') + fi + for label in ${LABELS}; do + if [ "$label" = "skip-ci" ]; then + SKIP_CI="true" + break + fi + done + echo "skip_ci=$SKIP_CI" >> $GITHUB_OUTPUT + + target-branch-check: + name: target-branch-check + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' || github.event_name == 'merge_group' + steps: + - name: Check that the pull request is not targeting the stable branch + run: test ${{ github.base_ref }} != "stable" + release-tests-ubuntu: + name: release-tests-ubuntu + needs: [check-labels] + if: needs.check-labels.outputs.skip_ci != 'true' + # Use self-hosted runners only on the sigp repo. + runs-on: ${{ github.repository == 'sigp/ssv' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + - name: Get latest version of stable Rust + if: env.SELF_HOSTED_RUNNERS == 'false' + uses: moonrepo/setup-rust@v1 + with: + channel: stable + cache-target: release + bins: cargo-nextest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run tests in release + run: make nextest-release + - name: Show cache stats + if: env.SELF_HOSTED_RUNNERS == 'true' + run: sccache --show-stats + release-tests-windows: + name: release-tests-windows + needs: [check-labels] + if: needs.check-labels.outputs.skip_ci != 'true' + runs-on: ${{ github.repository == 'sigp/ssv' && fromJson('["self-hosted", "windows", "CI"]') || 'windows-2019' }} + steps: + - uses: actions/checkout@v4 + - name: Get latest version of stable Rust + if: env.SELF_HOSTED_RUNNERS == 'false' + uses: moonrepo/setup-rust@v1 + with: + channel: stable + cache-target: release + bins: cargo-nextest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Install make + if: env.SELF_HOSTED_RUNNERS == 'false' + run: choco install -y make + - name: Set LIBCLANG_PATH + run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV + - name: Run tests in release + run: make nextest-release + - name: Show cache stats + if: env.SELF_HOSTED_RUNNERS == 'true' + run: sccache --show-stats + debug-tests-ubuntu: + name: debug-tests-ubuntu + needs: [check-labels] + if: needs.check-labels.outputs.skip_ci != 'true' + # Use self-hosted runners only on the sigp repo. + runs-on: ${{ github.repository == 'sigp/ssv' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + - name: Get latest version of stable Rust + if: env.SELF_HOSTED_RUNNERS == 'false' + uses: moonrepo/setup-rust@v1 + with: + channel: stable + bins: cargo-nextest + - name: Run tests in debug + run: make nextest-debug + - name: Show cache stats + if: env.SELF_HOSTED_RUNNERS == 'true' + run: sccache --show-stats + check-code: + name: check-code + runs-on: ubuntu-latest + env: + CARGO_INCREMENTAL: 1 + steps: + - uses: actions/checkout@v4 + - name: Get latest version of stable Rust + uses: moonrepo/setup-rust@v1 + with: + channel: stable + cache-target: release + components: rustfmt,clippy + bins: cargo-audit + - name: Check formatting with cargo fmt + run: make cargo-fmt + - name: Lint code for quality and style with Clippy + run: make lint + - name: Certify Cargo.lock freshness + run: git diff --exit-code Cargo.lock + - name: Typecheck benchmark code without running it + run: make check-benches + - name: Validate state_processing feature arbitrary-fuzz + run: make arbitrary-fuzz + - name: Run cargo audit + run: make audit-CI + - name: Run cargo vendor to make sure dependencies can be vendored for packaging, reproducibility and archival purpose + run: CARGO_HOME=$(readlink -f $HOME) make vendor + - name: Markdown-linter + run: make mdlint + check-msrv: + name: check-msrv + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust at Minimum Supported Rust Version (MSRV) + run: | + metadata=$(cargo metadata --no-deps --format-version 1) + msrv=$(echo $metadata | jq -r '.packages | map(select(.name == "ssv")) | .[0].rust_version') + rustup override set $msrv + - name: Run cargo check + run: cargo check --workspace + cargo-udeps: + name: cargo-udeps + needs: [check-labels] + if: needs.check-labels.outputs.skip_ci != 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Get latest version of nightly Rust + uses: moonrepo/setup-rust@v1 + with: + channel: nightly + bins: cargo-udeps + cache: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create Cargo config dir + run: mkdir -p .cargo + - name: Install custom Cargo config + run: cp -f .github/custom/config.toml .cargo/config.toml + - name: Run cargo udeps to identify unused crates in the dependency graph + run: make udeps + env: + # Allow warnings on Nightly + RUSTFLAGS: "" +# cli-check: +# name: cli-check +# needs: [check-labels] +# if: needs.check-labels.outputs.skip_ci != 'true' +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# - name: Get latest version of stable Rust +# uses: moonrepo/setup-rust@v1 +# with: +# channel: stable +# cache-target: release +# - name: Run Makefile to trigger the bash script +# run: make cli diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..9e18fec8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,127 @@ +# Contributors Guide + +SSV is an open-source Secret Shared Validator (SSV) client. We're community driven and +welcome all contribution. We aim to provide a constructive, respectful and fun +environment for collaboration. + +This guide is geared towards beginners. If you're an open-source veteran feel +free to just skim this document and get straight into crushing issues. + +## Why Contribute + +There are many reasons you might contribute to SSV. For example, you may +wish to: + +- contribute to the SSV ecosystem. +- work on low-level blockchain protocol problems +- contribute to the Ethereum ecosystem. +- work in the amazing Rust programming language. +- learn how to participate in open-source projects. +- expand your software development skills. +- flex your skills in a public forum to expand your career + opportunities (or simply for the fun of it). + +## How to Contribute + +Regardless of the reason, the process to begin contributing is very much the +same. We operate like a typical open-source project operating on GitHub: the +repository [Issues](https://github.com/sigp/ssv/issues) is where we +track what needs to be done and [Pull +Requests](https://github.com/sigp/ssv/pulls) is where code gets +reviewed. We use [discord](TODO) to chat +informally. + +### General Work-Flow + +We recommend the following work-flow for contributors: + +1. **Find an issue** to work on, either because it's interesting or suitable to + your skill-set. Use comments to communicate your intentions and ask + questions. +2. **Work in a feature branch** of your personal fork + (github.com/YOUR_NAME/ssv) of the main repository + (github.com/sigp/ssv). +3. Once you feel you have addressed the issue, **create a pull-request** with + `unstable` as the base branch to merge your changes into the main repository. +4. Wait for the repository maintainers to **review your changes** to ensure the + issue is addressed satisfactorily. Optionally, mention your PR on + [discord](TODO). +5. If the issue is addressed the repository maintainers will **merge your + pull-request** and you'll be an official contributor! + +Generally, you find an issue you'd like to work on and announce your intentions +to start work in a comment on the issue. Then, do your work on a separate +branch (a "feature branch") in your own fork of the main repository. Once +you're happy and you think the issue has been addressed, create a pull request +into the main repository. + +### First-time Set-up + +First time contributors can get their git environment up and running with these +steps: + +1. [Create a + fork](https://help.github.com/articles/fork-a-repo/#fork-an-example-repository) + and [clone + it](https://help.github.com/articles/fork-a-repo/#step-2-create-a-local-clone-of-your-fork) + to your local machine. +2. [Add an _"upstream"_ + branch](https://help.github.com/articles/fork-a-repo/#step-3-configure-git-to-sync-your-fork-with-the-original-spoon-knife-repository) + that tracks github.com/sigp/ssv using `$ git remote add upstream + https://github.com/sigp/ssv.git` ( + pro-tip: [use SSH](https://help.github.com/articles/connecting-to-github-with-ssh/) instead of HTTPS). +3. Create a new feature branch with `$ git checkout -b your_feature_name`. The + name of your branch isn't critical but it should be short and instructive. + E.g., if you're fixing a bug with serialization, you could name your branch + `fix_serialization_bug`. +4. Make sure you sign your commits. + See [relevant doc](https://help.github.com/en/github/authenticating-to-github/about-commit-signature-verification). +5. Commit your changes and push them to your fork with `$ git push origin + your_feature_name`. +6. Go to your fork on github.com and use the web interface to create a pull + request into the sigp/ssv repo. + +From there, the repository maintainers will review the PR and either accept it +or provide some constructive feedback. + +There's a great +[guide](https://akrabat.com/the-beginners-guide-to-contributing-to-a-github-project/) +by Rob Allen that provides much more detail on each of these steps, if you're +having trouble. As always, jump on [discord](https://discord.gg/cyAszAh) +if you get stuck. + +Additionally, +the ["Contributing to SSV" section](https://ssv-book.sigmaprime.io/contributing.html#contributing-to-ssv) +of the SSV Book provides more details on the setup. + +## FAQs + +### I don't think I have anything to add + +There's lots to be done and there's all sorts of tasks. You can do anything +from enhancing documentation through to writing core consensus code. If you reach out, +we'll include you. + +Please note, to maintain project quality, we may not accept PRs for small typos or changes +with minimal impact. + +### I'm not sure my Rust is good enough + +We're open to developers of all levels. If you create a PR and your code +doesn't meet our standards, we'll help you fix it and we'll share the reasoning +with you. Contributing to open-source is a great way to learn. + +### I'm not sure I know enough about SSV + +No problems, there's plenty of tasks that don't require extensive SSV +knowledge. You can learn about SSV as you go. + +### I'm afraid of making a mistake and looking silly + +Don't be. We're all about personal development and constructive feedback. If you +make a mistake and learn from it, everyone wins. + +### I don't like the way you do things + +Please, make an issue and explain why. We're open to constructive criticism and +will happily change our ways. diff --git a/Cargo.toml b/Cargo.toml index c1dcb83f..c0836597 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,8 @@ name = "ssv" version = "0.1.0" edition = "2021" -author = "Sigma Prime" +authors = ["Sigma Prime "] +rust-version = "1.80.0" [dependencies] task_executor = { path = "../sigp-crates/task_executor" } diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..9bd86254 --- /dev/null +++ b/Makefile @@ -0,0 +1,151 @@ +.PHONY: tests + +GIT_TAG := $(shell git describe --tags --candidates 1) +BIN_DIR = "bin" + +X86_64_TAG = "x86_64-unknown-linux-gnu" +BUILD_PATH_X86_64 = "target/$(X86_64_TAG)/release" +AARCH64_TAG = "aarch64-unknown-linux-gnu" +BUILD_PATH_AARCH64 = "target/$(AARCH64_TAG)/release" + +PINNED_NIGHTLY ?= nightly + +# List of features to use when cross-compiling. Can be overridden via the environment. +CROSS_FEATURES ?= jemalloc + +# Cargo profile for Cross builds. Default is for local builds, CI uses an override. +CROSS_PROFILE ?= release + +# List of features to use when running CI tests. +TEST_FEATURES ?= + +# Cargo profile for regular builds. +PROFILE ?= release + +# Extra flags for Cargo +CARGO_INSTALL_EXTRA_FLAGS?= + +# Builds the binary in release (optimized). +# +# Binaries will most likely be found in `./target/release` +install: + cargo install --path . --force --locked \ + --features "$(FEATURES)" \ + --profile "$(PROFILE)" \ + $(CARGO_INSTALL_EXTRA_FLAGS) + +# The following commands use `cross` to build a cross-compile. +# +# These commands require that: +# +# - `cross` is installed (`cargo install cross`). +# - Docker is running. +# - The current user is in the `docker` group. +# +# The resulting binaries will be created in the `target/` directory. +build-x86_64: + cross build --target x86_64-unknown-linux-gnu --features "$(CROSS_FEATURES)" --profile "$(CROSS_PROFILE)" --locked +build-aarch64: + cross build --target aarch64-unknown-linux-gnu --features "$(CROSS_FEATURES)" --profile "$(CROSS_PROFILE)" --locked + +# Create a `.tar.gz` containing a binary for a specific target. +define tarball_release_binary + cp $(1)/ssv $(BIN_DIR)/ssv + cd $(BIN_DIR) && \ + tar -czf ssv-$(GIT_TAG)-$(2)$(3).tar.gz ssv && \ + rm ssv +endef + +# Create a series of `.tar.gz` files in the BIN_DIR directory, each containing +# a `ssv` binary for a different target. +# +# The current git tag will be used as the version in the output file names. You +# will likely need to use `git tag` and create a semver tag (e.g., `v0.2.3`). +build-release-tarballs: + [ -d $(BIN_DIR) ] || mkdir -p $(BIN_DIR) + $(MAKE) build-x86_64 + $(call tarball_release_binary,$(BUILD_PATH_X86_64),$(X86_64_TAG),"") + $(MAKE) build-aarch64 + $(call tarball_release_binary,$(BUILD_PATH_AARCH64),$(AARCH64_TAG),"") + +# Runs the full workspace tests in **release**, without downloading any additional +# test vectors. +test-release: + cargo test --release --features "$(TEST_FEATURES)" + +# Runs the full workspace tests in **release**, without downloading any additional +# test vectors, using nextest. +nextest-release: + cargo nextest run --release --features "$(TEST_FEATURES)" + +# Runs the full workspace tests in **debug**, without downloading any additional test +# vectors. +test-debug: + cargo test --workspace --features "$(TEST_FEATURES)" + +# Runs the full workspace tests in **debug**, without downloading any additional test +# vectors, using nextest. +nextest-debug: + cargo nextest run --workspace --features "$(TEST_FEATURES)" + +# Runs cargo-fmt (linter). +cargo-fmt: + cargo fmt --all -- --check + +# Typechecks benchmark code +check-benches: + cargo check --workspace --benches --features "$(TEST_FEATURES)" + + +# Runs the full workspace tests in release, without downloading any additional +# test vectors. +test: test-release + +# Updates the CLI help text pages in the SSV book, building with Docker. +cli: + docker run --rm --user=root \ + -v ${PWD}:/home/runner/actions-runner/ssv sigmaprime/github-runner \ + bash -c 'cd ssv && make && ./scripts/cli.sh' + +# Updates the CLI help text pages in the SSV book, building using local +# `cargo`. +cli-local: + make && ./scripts/cli.sh + +# Check for markdown files +mdlint: + ./scripts/mdlint.sh + +# Runs the entire test suite +test-full: cargo-fmt test-release test-debug + +# Lints the code for bad style and potentially unsafe arithmetic using Clippy. +# Clippy lints are opt-in per-crate for now. By default, everything is allowed except for performance and correctness lints. +lint: + cargo clippy --workspace --tests $(EXTRA_CLIPPY_OPTS) --features "$(TEST_FEATURES)" -- \ + -D warnings + +# Lints the code using Clippy and automatically fix some simple compiler warnings. +lint-fix: + EXTRA_CLIPPY_OPTS="--fix --allow-staged --allow-dirty" $(MAKE) lint + +# Runs cargo audit (Audit Cargo.lock files for crates with security vulnerabilities reported to the RustSec Advisory Database) +audit: install-audit audit-CI + +install-audit: + cargo install --force cargo-audit + +audit-CI: + cargo audit + +# Runs `cargo vendor` to make sure dependencies can be vendored for packaging, reproducibility and archival purpose. +vendor: + cargo vendor + +# Runs `cargo udeps` to check for unused dependencies +udeps: + cargo +$(PINNED_NIGHTLY) udeps --tests --all-targets --release --features "$(TEST_FEATURES)" + +# Performs a `cargo` clean +clean: + cargo clean diff --git a/README.md b/README.md index eea146cc..ef370c42 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,38 @@ Open source implantation of the Secret Shared Validator (SSV) protocol, written in Rust and maintained by Sigma Prime. -[Book Status]:https://img.shields.io/badge/user--docs-unstable-informational +[![Book Status]][Book Link] [![Chat Badge]][Chat Link] + +[Book Status]:https://img.shields.io/badge/user--docs-stable-informational [Book Link]: https://ssv-book.sigmaprime.io [stable]: https://github.com/sigp/ssv/tree/stable [unstable]: https://github.com/sigp/ssv/tree/unstable [blog]: https://blog.sigmaprime.io + +## Overview + +This client implementation is currently under active development and should not +be used for production until a formal production release has been made. + +## Documentation + +The [SSV Book](https://ssv-book.sigmaprime.io) contains information for users and +developers. Instructions for how to compile/build and run this client are all +contained in this book. + +## Branches + +SSV maintains two permanent branches: + +- [`stable`][stable]: Always points to the latest stable release. + - This is ideal for most users. +- [`unstable`][unstable]: Used for development, contains the latest PRs. + - Developers should base their PRs on this branch. + +## Contributing + +SSV welcomes contributors. + +If you are looking to contribute, please head to the +[Contributing](https://ssv-book.sigmaprime.io/contributing.html) section +of the SSV book. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..e099c12b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +Please see [Releases](https://github.com/ssv/lighthouse/releases/). We recommend using the [most recently released version](https://github.com/sigp/ssv/releases/latest). + +## Reporting a Vulnerability + +Please send vulnerability reports to security@sigmaprime.io and encrypt sensitive messages using our [PGP +key](https://keybase.io/sigp/pgp_keys.asc?fingerprint=15e66d941f697e28f49381f426416dc3f30674b0). + +**Please do not file a public ticket** mentioning the vulnerability, as doing so could increase the likelihood of the vulnerability being used before a fix has been created, released and installed on the network. + diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 16daa8cc..66be9cdd 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -3,3 +3,5 @@ * [Introduction](./intro.md) * [FAQs](./faq.md) * [Protocol Developers](./developers.md) +* [Contributing](./contributing.md) + * [Development Environment](./setup.md) diff --git a/book/src/contributing.md b/book/src/contributing.md new file mode 100644 index 00000000..2b079f2e --- /dev/null +++ b/book/src/contributing.md @@ -0,0 +1,111 @@ +# Contributing to SSV + +[stable]: https://github.com/sigp/ssv/tree/stable +[unstable]: https://github.com/sigp/ssv/tree/unstable + +SSV welcomes contributions. If you are interested in contributing to to this project, and you want to learn Rust, feel free to join us building this project. + +To start contributing, + +1. Read our [how to contribute](https://github.com/sigp/ssv/blob/stable/CONTRIBUTING.md) document. +2. Setup a [development environment](./setup.md). +3. Browse through the [open issues](https://github.com/sigp/ssv/issues) + (tip: look for the [good first + issue](https://github.com/sigp/ssv/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) + tag). +4. Comment on an issue before starting work. +5. Share your work via a pull-request. + +## Branches + +SSV maintains two permanent branches: + +- [`stable`][stable]: Always points to the latest stable release. + - This is ideal for most users. +- [`unstable`][unstable]: Used for development, contains the latest PRs. + - Developers should base their PRs on this branch. + +## Rust + +We adhere to Rust code conventions as outlined in the [**Rust +Styleguide**](https://doc.rust-lang.org/nightly/style-guide/). + +Please use [clippy](https://github.com/rust-lang/rust-clippy) and +[rustfmt](https://github.com/rust-lang/rustfmt) to detect common mistakes and +inconsistent code formatting: + +```bash +cargo clippy --all +cargo fmt --all --check +``` + +### Panics + +Generally, **panics should be avoided at all costs**. SSV operates in an +adversarial environment (the Internet) and it's a severe vulnerability if +people on the Internet can cause SSV to crash via a panic. + +Always prefer returning a `Result` or `Option` over causing a panic. For +example, prefer `array.get(1)?` over `array[1]`. + +If you know there won't be a panic but can't express that to the compiler, +use `.expect("Helpful message")` instead of `.unwrap()`. Always provide +detailed reasoning in a nearby comment when making assumptions about panics. + +### TODOs + +All `TODO` statements should be accompanied by a GitHub issue. + +```rust +pub fn my_function(&mut self, _something &[u8]) -> Result { + // TODO: something_here + // https://github.com/sigp/lighthouse/issues/XX +} +``` + +### Comments + +**General Comments** + +- Prefer line (``//``) comments to block comments (``/* ... */``) +- Comments can appear on the line prior to the item or after a trailing space. + +```rust +// Comment for this struct +struct SSV {} +fn validate_attestation() {} // A comment on the same line after a space +``` + +**Doc Comments** + +- The ``///`` is used to generate comments for Docs. +- The comments should come before attributes. + +```rust +/// Stores the core configuration for this Lighthouse instance. +/// This struct is general, other components may implement more +/// specialized config structs. +#[derive(Clone)] +pub struct SSVConfig { + pub data_dir: PathBuf, + pub p2p_listen_port: u16, +} +``` + +### Rust Resources + +Rust is an extremely powerful, low-level programming language that provides +freedom and performance to create powerful projects. The [Rust +Book](https://doc.rust-lang.org/stable/book/) provides insight into the Rust +language and some of the coding style to follow (As well as acting as a great +introduction and tutorial for the language). + +Rust has a steep learning curve, but there are many resources to help. We +suggest: + +- [Rust Book](https://doc.rust-lang.org/stable/book/) +- [Rust by example](https://doc.rust-lang.org/stable/rust-by-example/) +- [Learning Rust With Entirely Too Many Linked Lists](http://cglab.ca/~abeinges/blah/too-many-lists/book/) +- [Rustlings](https://github.com/rustlings/rustlings) +- [Rust Exercism](https://exercism.io/tracks/rust) +- [Learn X in Y minutes - Rust](https://learnxinyminutes.com/docs/rust/) diff --git a/book/src/setup.md b/book/src/setup.md new file mode 100644 index 00000000..49ed7c32 --- /dev/null +++ b/book/src/setup.md @@ -0,0 +1,44 @@ +# Development Environment + +Most SSV developers work on Linux or MacOS, however Windows should still +be suitable. + +First, follow the [`Installation Guide`](./installation.md) to install +SSV. This will install SSV to your `PATH`, which is not +particularly useful for development but still a good way to ensure you have the +base dependencies. + +The additional requirements for developers are: + +- [`docker`](https://www.docker.com/). Some tests need docker installed and **running**. + +## Using `make` + +Commands to run the test suite are available via the `Makefile` in the +project root for the benefit of CI/CD. We list some of these commands below so +you can run them locally and avoid CI failures: + +- `$ make cargo-fmt`: (fast) runs a Rust code formatting check. +- `$ make lint`: (fast) runs a Rust code linter. +- `$ make test`: (medium) runs unit tests across the whole project. +- `$ make test-specs`: (medium) runs the SSV test vectors. +- `$ make test-full`: (slow) runs the full test suite (including all previous + commands). This is approximately everything + that is required to pass CI. + +## Testing + +As with most other Rust projects, SSV uses `cargo test` for unit and +integration tests. For example, to test the `qbft` crate run: + +```bash +$ cd src/qbft +$ cargo test +``` + +## Local Testnets + +During development and testing it can be useful to start a small, local +testnet. + +Testnet scripts will be built as the project develops. diff --git a/scripts/cli.sh b/scripts/cli.sh new file mode 100755 index 00000000..3d02fb2d --- /dev/null +++ b/scripts/cli.sh @@ -0,0 +1,79 @@ +#! /usr/bin/env bash + +# IMPORTANT +# This script should NOT be run directly. +# Run `make cli` or `make cli-local` from the root of the repository instead. + +set -e + +# A function to generate formatted .md files +write_to_file() { + local cmd="$1" + local file="$2" + local program="$3" + + # We need to add the header and the backticks to create the code block. + printf "# %s\n\n\`\`\`\n%s\n\`\`\`" "$program" "$cmd" > "$file" + + # Adjust the width of the help text and append to the end of file + sed -i -e '$a\'$'\n''\n''' "$file" +} + +CMD=./target/release/ssv + +# Store all help strings in variables. +general_cli=$($CMD --help) + +general=./help_general.md + +# create .md files +write_to_file "$general_cli" "$general" "SSV General Commands" + +#input 1 = $1 = files; input 2 = $2 = new files +files=(./book/src/help_general.md ./book/src/help_bn.md ./book/src/help_vc.md ./book/src/help_vm.md ./book/src/help_vm_create.md ./book/src/help_vm_import.md ./book/src/help_vm_move.md) +new_files=($general $bn $vc $vm $vm_create $vm_import $vm_move) + +# function to check +check() { + local file="$1" + local new_file="$2" + + if [[ -f $file ]]; then # check for existence of file + diff=$(diff $file $new_file || :) + else + cp $new_file $file + changes=true + echo "$file is not found, it has just been created" + fi + + if [[ -z $diff ]]; then # check for difference + : # do nothing + else + cp $new_file $file + changes=true + echo "$file has been updated" + fi +} + +# define changes as false +changes=false +# call check function to check for each help file +check ${files[0]} ${new_files[0]} +check ${files[1]} ${new_files[1]} +check ${files[2]} ${new_files[2]} +check ${files[3]} ${new_files[3]} +check ${files[4]} ${new_files[4]} +check ${files[5]} ${new_files[5]} +check ${files[6]} ${new_files[6]} + +# remove help files +rm -f help_general.md help_bn.md help_vc.md help_am.md help_vm.md help_vm_create.md help_vm_import.md help_vm_move.md + +# only exit at the very end +if [[ $changes == true ]]; then + echo "Exiting with error to indicate changes occurred. To fix, run 'make cli-local' or 'make cli' and commit the changes." + exit 1 +else + echo "CLI help texts are up to date." + exit 0 +fi diff --git a/scripts/mdlint.sh b/scripts/mdlint.sh new file mode 100755 index 00000000..55d8d1f9 --- /dev/null +++ b/scripts/mdlint.sh @@ -0,0 +1,23 @@ +#! /usr/bin/env bash + +# IMPORTANT +# This script should NOT be run directly. +# Run `make mdlint` from the root of the repository instead. + +# use markdownlint-cli to check for markdown files +docker run --rm -v ./book:/workdir ghcr.io/igorshubovych/markdownlint-cli:latest '**/*.md' --ignore node_modules + +# exit code +exit_code=$(echo $?) + +if [[ $exit_code == 0 ]]; then + echo "All markdown files are properly formatted." + exit 0 +elif [[ $exit_code == 1 ]]; then + echo "Exiting with errors. Run 'make mdlint' locally and commit the changes. Note that not all errors can be fixed automatically, if there are still errors after running 'make mdlint', look for the errors and fix manually." + docker run --rm -v ./book:/workdir ghcr.io/igorshubovych/markdownlint-cli:latest '**/*.md' --ignore node_modules --fix + exit 1 +else + echo "Exiting with exit code >1. Check for the error logs and fix them accordingly." + exit 1 +fi