diff --git a/.github/workflows/publish-rust.yml b/.github/workflows/publish-rust.yml new file mode 100644 index 0000000..cdd70c7 --- /dev/null +++ b/.github/workflows/publish-rust.yml @@ -0,0 +1,216 @@ +name: Publish Crate + +on: + workflow_dispatch: + inputs: + package_path: + description: Path to directory with package to release + required: true + type: string + level: + description: Level + required: true + default: patch + type: choice + options: + - patch + - minor + - major + - version + version: + description: Version (used with level "version") + required: false + type: string + dry_run: + description: Dry run + required: true + default: true + type: boolean + create_release: + description: Create a GitHub release + required: true + type: boolean + default: true + dependent_version: + description: | + How workspace dependencies should be handled. + - "fix": (Default) Only bumps the workspace for semver-breakage - prefer this option + - "upgrade": Bumps workspace version regardless - only use if another crate requires new code + required: true + default: fix + type: choice + options: + - fix + - upgrade + run_semver: + description: | + Run semver checks. + Only disable checks if you are sure of the semver impact of your change and have a good reason + to skip it. + required: true + type: boolean + default: true + +jobs: + format: + name: Format + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + + - name: Cache + uses: Swatinem/rust-cache@v2 + + - name: Check formatting + run: cargo fmt --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Cache + uses: Swatinem/rust-cache@v2 + + - name: Run clippy + run: cargo clippy --workspace --all-targets -- -D warnings + + semver: + name: Check Semver + runs-on: ubuntu-latest + steps: + - name: Git checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache + uses: Swatinem/rust-cache@v2 + + - name: Install tools + uses: taiki-e/install-action@v2 + with: + tool: toml-cli,cargo-semver-checks,cargo-release + + - name: Check if crate is a procedural macro + id: is_proc_macro + shell: bash + run: | + set +e # toml crashes the whole shell if it fails to find the key + result=$(toml get "${{ inputs.package_path }}/Cargo.toml" lib.proc-macro) + if [[ "$result" == *"true"* ]]; then + echo "is_proc_macro=true" >> "$GITHUB_OUTPUT" + else + echo "is_proc_macro=false" >> "$GITHUB_OUTPUT" + fi + + - name: Set Git Author (required for cargo-release) + if: ${{ steps.is_proc_macro.outputs.is_proc_macro == 'false' }} + run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + + - name: Set Version + if: ${{ steps.is_proc_macro.outputs.is_proc_macro == 'false' }} + run: | + if [ "${{ inputs.level }}" == "version" ]; then + LEVEL=${{ inputs.version }} + else + LEVEL=${{ inputs.level }} + fi + cargo release $LEVEL --manifest-path "${{ inputs.package_path }}/Cargo.toml" --no-tag --no-publish --no-push --no-confirm --execute + + - name: Check semver + if: ${{ steps.is_proc_macro.outputs.is_proc_macro == 'false' && github.event.inputs.run_semver == 'true'}} + run: cargo semver-checks --manifest-path "${{ inputs.package_path }}/Cargo.toml" + + publish-crate: + name: Publish crate + runs-on: ubuntu-latest + needs: [format, clippy, semver] + permissions: + contents: write + steps: + - name: Git Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.ANZA_TEAM_PAT }} + fetch-depth: 0 # get the whole history for git-cliff + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache + uses: Swatinem/rust-cache@v2 + + - name: Install cargo-release + uses: taiki-e/install-action@v2 + with: + tool: cargo-release + + - name: Ensure CARGO_REGISTRY_TOKEN variable is set + env: + token: ${{ secrets.CARGO_REGISTRY_TOKEN }} + if: ${{ env.token == '' }} + run: | + echo "The CARGO_REGISTRY_TOKEN secret variable is not set" + echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." + exit 1 + + - name: Set Git Author + run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + + - name: Rebase (in case any changes landed after) + run: git pull --rebase origin + + - name: Publish Crate + id: publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: | + if [ "${{ inputs.level }}" == "version" ]; then + LEVEL=${{ inputs.version }} + else + LEVEL=${{ inputs.level }} + fi + + if [ "${{ inputs.dry_run }}" == "true" ]; then + OPTIONS="--dry-run" + else + OPTIONS="" + fi + + ./scripts/publish-rust.sh "${{ inputs.package_path }}" $LEVEL "${{ inputs.dependent_version }}" $OPTIONS + + - name: Generate a changelog + if: github.event.inputs.create_release == 'true' + uses: orhun/git-cliff-action@v4 + with: + config: "scripts/cliff.toml" + args: ${{ steps.publish.outputs.old_git_tag }}..HEAD --include-path "${{ inputs.package_path }}/**" --github-repo ${{ github.repository }} + env: + OUTPUT: TEMP_CHANGELOG.md + GITHUB_REPO: ${{ github.repository }} + + - name: Create GitHub release + if: github.event.inputs.create_release == 'true' && github.event.inputs.dry_run != 'true' + uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.publish.outputs.new_git_tag }} + bodyFile: TEMP_CHANGELOG.md diff --git a/Cargo.lock b/Cargo.lock index 0e4e3e3..ec252fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,9 +132,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.58" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "shlex", @@ -466,9 +466,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fiat-crypto" @@ -615,9 +615,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ "typenum", ] @@ -630,9 +630,9 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -677,9 +677,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.92" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ "once_cell", "wasm-bindgen", @@ -693,9 +693,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "linux-raw-sys" @@ -1404,9 +1404,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -1752,9 +1752,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.115" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ "cfg-if", "once_cell", @@ -1765,9 +1765,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.115" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1775,9 +1775,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.115" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ "bumpalo", "proc-macro2", @@ -1788,9 +1788,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.115" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] @@ -1831,9 +1831,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.92" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/curve25519/solana-ed25519/README.md b/curve25519/solana-ed25519/README.md index 7557d52..6dd6ce8 100644 --- a/curve25519/solana-ed25519/README.md +++ b/curve25519/solana-ed25519/README.md @@ -102,38 +102,6 @@ curve25519 = { package = "solana-ed25519", git = "https://github.com/anza-xyz/cr use core::convert::TryFrom; use curve25519::ed_sigs::{SigningKey, VerificationKey}; -let msg = b"solana-ed25519"; - -// Generate key and sign -let sk = SigningKey::new(rand::rng()); -let sig = sk.sign(msg); -let vk = VerificationKey::from(&sk); - -// Standard ZIP-215 verification (from ed25519-zebra) -vk.verify(&sig, msg).expect("valid signature"); - -// HEEA-accelerated verification (same result, ~15% faster) -vk.verify_zebra(&sig, msg).expect("valid signature"); -``` - -### Batch verification - -```rust,ignore -use curve25519::ed_sigs::batch; - -let mut verifier = batch::Verifier::new(); -for (vk_bytes, sig, msg) in items { - verifier.queue((vk_bytes, sig, msg)); -} -verifier.verify(rand::rng()).expect("all valid"); -``` - -### Ed25519 signing and verification - -```rust,no_run -use core::convert::TryFrom; -use curve25519::ed_sigs::{SigningKey, VerificationKey}; - let msg = b"curve25519-sol"; // Generate key and sign diff --git a/scripts/cliff.toml b/scripts/cliff.toml new file mode 100644 index 0000000..7c8ea7f --- /dev/null +++ b/scripts/cliff.toml @@ -0,0 +1,49 @@ +# git-cliff configuration file +# https://git-cliff.org/docs/configuration +[changelog] +header = """ +## What's new +""" +body = """ +{% for group, commits in commits | group_by(attribute="group") %}\ + {% for commit in commits %} + - {{ commit.message | upper_first | split(pat="\n") | first | trim }}\ + {% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif %}\ + {% endfor %}\ +{% endfor %} +""" +# remove the leading and trailing whitespace from the template +trim = true +footer = """ +""" +postprocessors = [ ] +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = false +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^build\\(deps\\)", skip = true }, + { message = "^build\\(deps-dev\\)", skip = true }, + { message = "^ci", skip = true }, + { body = ".*", group = "Changes" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "" +# regex for ignoring tags +ignore_tags = "" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "newest" diff --git a/scripts/publish-rust.sh b/scripts/publish-rust.sh new file mode 100755 index 0000000..a7e4e4d --- /dev/null +++ b/scripts/publish-rust.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +set -e +base="$(dirname "${BASH_SOURCE[0]}")" +# pacify shellcheck: cannot follow dynamic path +# shellcheck disable=SC1090,SC1091 +source "$base/read-cargo-variable.sh" +cd "$base/.." + +if [[ -z $1 ]]; then + echo 'A package manifest path — e.g. "curve25519/solana-ed25519" — must be provided.' + exit 1 +fi +PACKAGE_PATH=$1 +if [[ -z $2 ]]; then + echo 'A version level — e.g. "patch" — must be provided.' + exit 1 +fi +LEVEL=$2 +DEPENDENT_VERSION=$3 +DRY_RUN=$4 + +# Go to the directory +cd "${PACKAGE_PATH}" + +# Get the old version, used with git-cliff +old_version=$(readCargoVariable version "Cargo.toml") +package_name=$(readCargoVariable name "Cargo.toml") +tag_name="${package_name}" + +# Publish the new version, commit the repo change, tag it, and push it all. +if [[ -n ${DRY_RUN} ]]; then + cargo release "${LEVEL}" +else + cargo release "${LEVEL}" --tag-name "${tag_name}@v{{version}}" --no-confirm --execute --dependent-version "${DEPENDENT_VERSION}" +fi + +# Stop here if this is a dry run. +if [[ -n $DRY_RUN ]]; then + exit 0 +fi + +# Get the new version. +new_version=$(readCargoVariable version "Cargo.toml") +new_git_tag="${tag_name}@v${new_version}" +old_git_tag="${tag_name}@v${old_version}" + +# Expose the new version to CI if needed. +if [[ -n $CI ]]; then + echo "new_git_tag=${new_git_tag}" >> "$GITHUB_OUTPUT" + echo "old_git_tag=${old_git_tag}" >> "$GITHUB_OUTPUT" +fi diff --git a/scripts/read-cargo-variable.sh b/scripts/read-cargo-variable.sh new file mode 100644 index 0000000..7f6c951 --- /dev/null +++ b/scripts/read-cargo-variable.sh @@ -0,0 +1,14 @@ +# source this file + +readCargoVariable() { + declare variable="$1" + declare Cargo_toml="$2" + + while read -r name equals value _; do + if [[ $name = "$variable" && $equals = = ]]; then + echo "${value//\"/}" + return + fi + done < <(cat "$Cargo_toml") + echo "Unable to locate $variable in $Cargo_toml" 1>&2 +}