-
Notifications
You must be signed in to change notification settings - Fork 24
[WIP] Confidential transfers #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
60bcd0f
cab9de4
b2f2aac
e680fa9
4cb7921
0180c89
f23b97d
ea525e0
5f9c0ff
571e0b1
d6699e3
9315cf2
5228a05
4d9e60a
8b27c61
b6a27fe
b6129a9
2f8205a
9fe2a21
8a5366b
6f550c2
efa62f1
692e057
04d9c19
ce2ac3d
db00219
c29a421
ced1a97
9667280
4ca4f8d
df8e4ca
b349d6d
cc50b72
d495680
471a346
0a5fe4e
3e28b7a
0cf28ba
5bef406
92529df
3749f99
66a42a2
c8ea4d1
6e92705
734bc82
65ed5d6
614d1db
dc8b114
33cca88
425e3b8
ebd425c
439dff4
466209f
d912ee0
29c5344
df79a7e
e3806e4
1e1c72a
a49b9d6
1d27dfd
623632e
d0ee46d
2967ffe
da53339
c3326e1
87adeaf
daab02a
7138c42
08da98d
6620830
088cfd2
4d8ac31
a18799c
937171e
ffd0a90
e7520a5
cb15e6b
a386a3a
d118dfc
200d219
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,394 @@ | ||
| name: Build mpt-crypto | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "mpt-crypto version (leave empty for latest)" | ||
| required: false | ||
| default: "" | ||
| force: | ||
| description: "Rebuild even when the version or update branch already exists" | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| schedule: | ||
| - cron: "0 9 * * 1" # Every Monday at 9:00 UTC | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| check: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| version: ${{ steps.resolve.outputs.version }} | ||
| current: ${{ steps.resolve.outputs.current }} | ||
| needed: ${{ steps.resolve.outputs.needed }} | ||
| branch: ${{ steps.resolve.outputs.branch }} | ||
| steps: | ||
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Install Conan | ||
| run: | | ||
| pip install "conan==2.26.2" | ||
| conan profile detect | ||
| conan remote add --index 0 xrplf https://conan.ripplex.io | ||
|
|
||
| - name: Resolve version and check if update needed | ||
| id: resolve | ||
| env: | ||
| REQUESTED_VERSION: ${{ inputs.version }} | ||
| FORCE_UPDATE: ${{ github.event_name == 'workflow_dispatch' && inputs.force }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| CURRENT=$(cat confidential/deps/VERSION 2>/dev/null || echo "") | ||
| echo "current=$CURRENT" >> "$GITHUB_OUTPUT" | ||
|
|
||
| if [ -n "$REQUESTED_VERSION" ]; then | ||
| VERSION="$REQUESTED_VERSION" | ||
| else | ||
| VERSION=$(conan list 'mpt-crypto/*' -r xrplf --format=json \ | ||
| | python3 -c ' | ||
| import json | ||
| import re | ||
| import sys | ||
|
|
||
| packages = json.load(sys.stdin) | ||
| versions = [ | ||
| reference.split("/", 1)[1] | ||
| for remote in packages.values() | ||
| for reference in remote | ||
| if reference.startswith("mpt-crypto/") | ||
| ] | ||
| if not versions: | ||
| raise SystemExit("no mpt-crypto versions found") | ||
|
|
||
| def version_key(version): | ||
| match = re.fullmatch(r"(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?", version) | ||
| if not match: | ||
| raise SystemExit(f"unsupported mpt-crypto version format: {version}") | ||
| prerelease = match.group(4) | ||
| prerelease_key = tuple( | ||
| (0, int(part)) if part.isdigit() else (1, part) | ||
| for part in re.split(r"[.-]", prerelease or "") | ||
| ) | ||
| return (*(int(match.group(index)) for index in range(1, 4)), prerelease is None, prerelease_key) | ||
|
|
||
| print(max(versions, key=version_key)) | ||
| ') | ||
| fi | ||
|
|
||
| if [[ ! "$VERSION" =~ ^[0-9A-Za-z][0-9A-Za-z._+-]*$ ]]; then | ||
| echo "::error::Invalid mpt-crypto version '$VERSION'" | ||
| exit 1 | ||
| fi | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
|
|
||
| BUNDLE_COMPLETE=true | ||
| for platform in linux-amd64 linux-arm64 darwin-amd64 darwin-arm64; do | ||
| for archive in libmpt-crypto.a libsecp256k1.a libcrypto.a; do | ||
| [ -s "confidential/deps/libs/$platform/$archive" ] || BUNDLE_COMPLETE=false | ||
| done | ||
| done | ||
| for header in mpt_protocol.h secp256k1_mpt.h secp256k1.h utility/mpt_utility.h; do | ||
| [ -s "confidential/deps/include/$header" ] || BUNDLE_COMPLETE=false | ||
| done | ||
| if [ "$BUNDLE_COMPLETE" = true ] && ! cc \ | ||
| -Iconfidential/deps/include \ | ||
| -Iconfidential/deps/include/utility \ | ||
| -x c -fsyntax-only - >/dev/null 2>&1 <<'EOF'; then | ||
| #include "mpt_utility.h" | ||
| int main(void) { return 0; } | ||
| EOF | ||
| BUNDLE_COMPLETE=false | ||
| fi | ||
|
|
||
| if [ "$FORCE_UPDATE" = "true" ]; then | ||
| BRANCH="chore/update-mpt-crypto-${VERSION}-run-${GITHUB_RUN_ID}" | ||
| echo "needed=true" >> "$GITHUB_OUTPUT" | ||
| echo "Forced rebuild requested for mpt-crypto/$VERSION." | ||
| else | ||
| BRANCH="chore/update-mpt-crypto-${VERSION}" | ||
| if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then | ||
| echo "needed=false" >> "$GITHUB_OUTPUT" | ||
| echo "::warning::Branch '$BRANCH' already exists. Enable force to create a new update branch." | ||
| elif [ "$CURRENT" = "$VERSION" ] && [ "$BUNDLE_COMPLETE" = true ]; then | ||
| echo "needed=false" >> "$GITHUB_OUTPUT" | ||
| echo "Already at a complete mpt-crypto/$VERSION bundle — skipping build." | ||
| else | ||
| echo "needed=true" >> "$GITHUB_OUTPUT" | ||
| echo "Building mpt-crypto/$VERSION for bundle validation ($CURRENT -> $VERSION)." | ||
| fi | ||
| fi | ||
| echo "branch=$BRANCH" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Lock resolved Conan graph | ||
| if: steps.resolve.outputs.needed == 'true' | ||
| env: | ||
| MPT_CRYPTO_VERSION: ${{ steps.resolve.outputs.version }} | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p .mpt-crypto-lock | ||
| cat > .mpt-crypto-lock/conanfile.txt <<EOF | ||
| [requires] | ||
| mpt-crypto/$MPT_CRYPTO_VERSION | ||
| EOF | ||
| conan lock create .mpt-crypto-lock/conanfile.txt \ | ||
| -o "*:shared=False" \ | ||
| -o "*:fPIC=True" \ | ||
| -s os=Linux \ | ||
| -s arch=x86_64 \ | ||
| --lockfile-out=.mpt-crypto-lock/conan.lock | ||
|
|
||
| - name: Upload Conan lockfile | ||
| if: steps.resolve.outputs.needed == 'true' | ||
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | ||
| with: | ||
| name: conan-lock | ||
| if-no-files-found: error | ||
| retention-days: 1 | ||
| path: .mpt-crypto-lock/conan.lock | ||
|
|
||
| build: | ||
| needs: check | ||
| if: needs.check.outputs.needed == 'true' | ||
| strategy: | ||
| matrix: | ||
| include: | ||
| - os: ubuntu-22.04 | ||
| platform: linux-amd64 | ||
| - os: ubuntu-22.04-arm | ||
| platform: linux-arm64 | ||
| - os: macos-latest | ||
| platform: darwin-arm64 | ||
| - os: macos-15-intel | ||
| platform: darwin-amd64 | ||
|
|
||
| runs-on: ${{ matrix.os }} | ||
| steps: | ||
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Download Conan lockfile | ||
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | ||
| with: | ||
| name: conan-lock | ||
| path: .mpt-crypto-lock/ | ||
|
|
||
| - name: Install Conan | ||
| run: | | ||
| set -euo pipefail | ||
| pip install "conan==2.26.2" | ||
| conan profile detect | ||
|
|
||
| # Hosted runners can ship compilers newer than Conan's bundled | ||
| # settings.yml. Extend, rather than replace, the supported versions | ||
| # with the compiler version detected in the ephemeral runner profile. | ||
| conan_home=$(conan config home) | ||
| profile="$conan_home/profiles/default" | ||
| compiler=$(sed -n 's/^compiler=//p' "$profile") | ||
| compiler_version=$(sed -n 's/^compiler.version=//p' "$profile") | ||
| if [ -z "$compiler" ] || [ -z "$compiler_version" ]; then | ||
| echo "::error::Could not read compiler settings from $profile" | ||
| exit 1 | ||
| fi | ||
| cat > "$conan_home/settings_user.yml" <<EOF | ||
| compiler: | ||
| $compiler: | ||
| version: ["$compiler_version"] | ||
| EOF | ||
| conan profile show -pr:h default >/dev/null | ||
|
|
||
| conan remote add --index 0 xrplf https://conan.ripplex.io | ||
|
|
||
| - name: Build CGO dependency bundle | ||
| env: | ||
| MPT_CRYPTO_VERSION: ${{ needs.check.outputs.version }} | ||
| TARGET_PLATFORM: ${{ matrix.platform }} | ||
| run: | | ||
| set -euo pipefail | ||
| bash confidential/deps/update.sh \ | ||
| --platform "$TARGET_PLATFORM" \ | ||
| --force \ | ||
| --version "$MPT_CRYPTO_VERSION" \ | ||
| --lockfile "$GITHUB_WORKSPACE/.mpt-crypto-lock/conan.lock" | ||
|
|
||
| - name: Verify CGO dependency bundle | ||
| env: | ||
| TARGET_PLATFORM: ${{ matrix.platform }} | ||
| run: | | ||
| set -euo pipefail | ||
| for archive in libmpt-crypto.a libsecp256k1.a libcrypto.a; do | ||
| path="confidential/deps/libs/$TARGET_PLATFORM/$archive" | ||
| test -s "$path" | ||
| ar -t "$path" >/dev/null | ||
| done | ||
|
|
||
| header_manifest="$GITHUB_WORKSPACE/confidential/deps/MANIFEST.sha256" | ||
| ( | ||
| cd confidential/deps/include | ||
| find . -type f -name '*.h' -print | | ||
| LC_ALL=C sort | | ||
| while IFS= read -r header; do shasum -a 256 "$header"; done | ||
| ) > "$header_manifest" | ||
| (cd confidential/deps/include && shasum -a 256 -c "$header_manifest") | ||
|
|
||
| cc \ | ||
| -Iconfidential/deps/include \ | ||
| -Iconfidential/deps/include/utility \ | ||
| -x c -fsyntax-only - <<'EOF' | ||
| #include "mpt_utility.h" | ||
| int main(void) { return 0; } | ||
| EOF | ||
|
|
||
| - name: Upload platform artifact | ||
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | ||
| with: | ||
| name: mpt-crypto-${{ matrix.platform }} | ||
| if-no-files-found: error | ||
| path: | | ||
| confidential/deps/VERSION | ||
| confidential/deps/MANIFEST.sha256 | ||
| confidential/deps/include/ | ||
| confidential/deps/libs/${{ matrix.platform }}/ | ||
|
|
||
| pr: | ||
| needs: [check, build] | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| steps: | ||
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Download all platform artifacts | ||
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | ||
| with: | ||
| path: artifacts/ | ||
|
|
||
| - name: Validate and merge artifacts into repo | ||
| env: | ||
| EXPECTED_VERSION: ${{ needs.check.outputs.version }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| merge_dir=$(mktemp -d) | ||
| trap 'rm -rf "$merge_dir"' EXIT | ||
| mkdir -p "$merge_dir/libs" | ||
|
|
||
| header_source="" | ||
| manifest_source="" | ||
| artifact_count=0 | ||
| for dir in artifacts/mpt-crypto-*/; do | ||
| artifact_count=$((artifact_count + 1)) | ||
| platform=$(basename "$dir" | sed 's/mpt-crypto-//') | ||
| case "$platform" in | ||
| linux-amd64|linux-arm64|darwin-amd64|darwin-arm64) ;; | ||
| *) echo "::error::Unexpected platform artifact: $platform"; exit 1 ;; | ||
| esac | ||
|
|
||
| actual_version=$(cat "$dir/VERSION") | ||
| if [ "$actual_version" != "$EXPECTED_VERSION" ]; then | ||
| echo "::error::$platform artifact has version $actual_version, expected $EXPECTED_VERSION" | ||
| exit 1 | ||
| fi | ||
|
|
||
| source_libs="$dir/libs/$platform" | ||
| archive_count=$(find "$source_libs" -maxdepth 1 -type f -name '*.a' | wc -l | tr -d ' ') | ||
| if [ "$archive_count" -ne 3 ]; then | ||
| echo "::error::$platform artifact contains $archive_count archives, expected 3" | ||
| exit 1 | ||
| fi | ||
|
|
||
| mkdir -p "$merge_dir/libs/$platform" | ||
| for archive in libmpt-crypto.a libsecp256k1.a libcrypto.a; do | ||
| if [ ! -s "$source_libs/$archive" ]; then | ||
| echo "::error::$platform artifact is missing $archive" | ||
| exit 1 | ||
| fi | ||
| cp "$source_libs/$archive" "$merge_dir/libs/$platform/" | ||
| done | ||
|
|
||
| artifact_manifest="$dir/MANIFEST.sha256" | ||
| if [ ! -s "$artifact_manifest" ]; then | ||
| echo "::error::$platform artifact is missing its header checksum manifest" | ||
| exit 1 | ||
| fi | ||
| artifact_manifest=$(cd "$(dirname "$artifact_manifest")" && pwd)/$(basename "$artifact_manifest") | ||
| (cd "$dir/include" && shasum -a 256 -c "$artifact_manifest") | ||
|
|
||
| if [ -z "$header_source" ]; then | ||
| header_source="$dir/include" | ||
| manifest_source="$artifact_manifest" | ||
| elif ! cmp -s "$manifest_source" "$artifact_manifest"; then | ||
| echo "::error::Public header checksums differ between platform artifacts" | ||
| exit 1 | ||
| elif ! diff -qr "$header_source" "$dir/include"; then | ||
| echo "::error::Public headers differ between platform artifacts" | ||
| exit 1 | ||
| fi | ||
| done | ||
|
|
||
| if [ "$artifact_count" -ne 4 ]; then | ||
| echo "::error::Found $artifact_count platform artifacts, expected 4" | ||
| exit 1 | ||
| fi | ||
|
|
||
| mkdir -p "$merge_dir/include" | ||
| cp -R "$header_source/." "$merge_dir/include/" | ||
| for header in mpt_protocol.h secp256k1_mpt.h secp256k1.h utility/mpt_utility.h; do | ||
| if [ ! -s "$merge_dir/include/$header" ]; then | ||
| echo "::error::Merged artifact is missing public header $header" | ||
| exit 1 | ||
| fi | ||
| done | ||
|
|
||
| rm -rf confidential/deps/libs confidential/deps/include | ||
| cp -R "$merge_dir/libs" confidential/deps/libs | ||
| cp -R "$merge_dir/include" confidential/deps/include | ||
| printf '%s\n' "$EXPECTED_VERSION" > confidential/deps/VERSION | ||
|
|
||
| - name: Create PR | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| VERSION: ${{ needs.check.outputs.version }} | ||
| CURRENT_VERSION: ${{ needs.check.outputs.current }} | ||
| UPDATE_BRANCH: ${{ needs.check.outputs.branch }} | ||
| BASE_BRANCH: ${{ github.ref_name }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git checkout -b "$UPDATE_BRANCH" | ||
| git add -f confidential/deps/ | ||
| if git diff --cached --quiet; then | ||
| echo "The rebuilt dependency bundle is unchanged; no PR is required." | ||
| exit 0 | ||
| fi | ||
| git commit -m "chore(confidential): update vendored mpt-crypto to $VERSION" | ||
| gh auth setup-git | ||
| git push -u origin "$UPDATE_BRANCH" | ||
|
|
||
| gh pr create \ | ||
| --base "$BASE_BRANCH" \ | ||
| --title "Update vendored mpt-crypto to $VERSION" \ | ||
| --body "$(cat <<EOF | ||
| Automated update of the vendored mpt-crypto CGO dependency bundle. | ||
|
|
||
| **$CURRENT_VERSION → $VERSION** | ||
|
|
||
| The workflow built and tested the complete static-library and public-header bundle on: | ||
| - linux-amd64 | ||
| - linux-arm64 | ||
| - darwin-arm64 | ||
| - darwin-amd64 | ||
| EOF | ||
| )" | ||
|
Comment on lines
+365
to
+394
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🧹 Fixed in commit a386a3a 🧹 |
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using variable interpolation${{...}}withgithubcontext data in arun:step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code.githubcontext data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable withenv:to store the data and use the environment variable in therun:script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".🎉 Fixed in commit a386a3a 🎉