From 28584ea74c338a35bf3b1ef0bc910c73d0057ca7 Mon Sep 17 00:00:00 2001 From: ziggieXXX <90319354+ziggie1984@users.noreply.github.com> Date: Fri, 5 Jun 2026 17:00:30 -0300 Subject: [PATCH] ci: require OTS proofs for final releases --- .github/workflows/release.yaml | 5 ++- .github/workflows/verify-release.yaml | 58 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 088c2cbab3b..c2d8a3693cc 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -81,11 +81,12 @@ jobs: ## Verifying the Release Timestamp - From this new version onwards, in addition time-stamping the _git tag_ with [OpenTimestamps](https://opentimestamps.org/), we'll also now timestamp the manifest file along with its signature. Two new files are now included along with the rest of our release artifacts: ` manifest-roasbeef-${{ env.RELEASE_VERSION }}.txt.asc.ots`. + From this new version onwards, in addition time-stamping the _git tag_ with [OpenTimestamps](https://opentimestamps.org/), we'll also now timestamp the manifest file along with at least one developer signature. Timestamp proof files are included along with the rest of our release artifacts: `manifest-${{ env.RELEASE_VERSION }}.txt.ots` and one or more `manifest--${{ env.RELEASE_VERSION }}.sig.ots` files. Assuming you have the opentimestamps client installed locally, the timestamps can be verified with the following commands: ``` - ots verify manifest-roasbeef-${{ env.RELEASE_VERSION }}.sig.ots -f manifest-roasbeef-${{ env.RELEASE_VERSION }}.sig + ots verify manifest-${{ env.RELEASE_VERSION }}.txt.ots -f manifest-${{ env.RELEASE_VERSION }}.txt + ots verify manifest--${{ env.RELEASE_VERSION }}.sig.ots -f manifest--${{ env.RELEASE_VERSION }}.sig ``` Alternatively, [the OpenTimestamps website](https://opentimestamps.org/) can be used to verify timestamps if one doesn't have a `bitcoind` instance accessible locally. diff --git a/.github/workflows/verify-release.yaml b/.github/workflows/verify-release.yaml index a9aaa267d70..b18f1eb3408 100644 --- a/.github/workflows/verify-release.yaml +++ b/.github/workflows/verify-release.yaml @@ -17,6 +17,64 @@ jobs: name: Verify release signatures and binaries runs-on: ubuntu-latest steps: + - name: git checkout + uses: actions/checkout@v4 + + - name: Check final release OpenTimestamps asset + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ inputs.version || github.event.release.tag_name }} + run: | + set -euo pipefail + + if [[ "${VERSION}" =~ \.rc[0-9]+$ ]]; then + echo "Release candidate ${VERSION}; skipping OpenTimestamps asset check." + exit 0 + fi + + REQUIRED_MANIFEST_OTS="manifest-${VERSION}.txt.ots" + TRUSTED_SIGNERS="$(sed -n \ + 's/^KEYS+=(.* \([^" ]*\)")$/\1/p' \ + scripts/verify-install.sh)" + + ASSETS="$(gh release view "${VERSION}" \ + --repo "${{ github.repository }}" \ + --json assets \ + --jq '.assets[].name')" + + if ! grep -Fxq "${REQUIRED_MANIFEST_OTS}" <<< "${ASSETS}"; then + echo "ERROR: Final release ${VERSION} is missing ${REQUIRED_MANIFEST_OTS}." + exit 1 + fi + + MATCHING_SIG="" + MATCHING_SIG_OTS="" + while IFS= read -r asset; do + if [[ "${asset}" != manifest-*-"${VERSION}".sig.ots ]]; then + continue + fi + + sig="${asset%.ots}" + signer="${sig%-$VERSION.sig}" + signer="${signer#manifest-}" + if grep -Fxq "${signer}" <<< "${TRUSTED_SIGNERS}" && + grep -Fxq "${sig}" <<< "${ASSETS}"; then + + MATCHING_SIG="${sig}" + MATCHING_SIG_OTS="${asset}" + break + fi + done <<< "${ASSETS}" + + if [[ -z "${MATCHING_SIG_OTS}" ]]; then + echo "ERROR: Final release ${VERSION} is missing an OpenTimestamps proof for an uploaded manifest signature." + exit 1 + fi + + echo "Found required OpenTimestamps artifacts:" + echo " ${REQUIRED_MANIFEST_OTS}" + echo " ${MATCHING_SIG_OTS} for ${MATCHING_SIG}" + - name: Verify release env: VERSION: ${{ inputs.version || github.event.release.tag_name }}