From 155c294a1887a3042e59d713d27170ded7ae5016 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Tue, 2 Feb 2021 11:44:43 -0800 Subject: [PATCH 1/4] add build script, extend github actions Signed-off-by: Andrew Whitehead --- .github/workflows/build.yml | 138 +++++++++++++++++++++++++++++++++ .github/workflows/rusttest.yml | 51 ++++++------ build.sh | 95 +++++++++++++++++++++++ 3 files changed, 257 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100755 build.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..cbeda1b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,138 @@ +name: "Build Packages" + +on: workflow_dispatch + +defaults: + run: + shell: bash + +jobs: + build-manylinux: + name: Build Library (Manylinux) + + strategy: + matrix: + include: + - os: ubuntu-latest + lib: libindy_credx.so + container: andrewwhitehead/manylinux2014-base + + container: ${{ matrix.container }} + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + + - name: Cache cargo resources + uses: Swatinem/rust-cache@v1 + + - name: Build library + env: + BUILD_TARGET: ${{ matrix.target }} + run: ./build.sh + + - name: Upload library artifacts + uses: actions/upload-artifact@v2 + with: + name: library-${{ runner.os }} + path: target/release/${{ matrix.lib }} + + build-other: + name: Build Library (MacOS/Win) + + strategy: + matrix: + include: + - os: macos-latest # macos-11.0 for universal + lib: libindy_credx.dylib + # target: apple-darwin + toolchain: stable # beta for universal + - os: windows-latest + lib: indy_credx.dll + toolchain: stable + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.toolchain }} + + - name: Cache cargo resources + uses: Swatinem/rust-cache@v1 + + - name: Build library + env: + BUILD_TARGET: ${{ matrix.target }} + BUILD_TOOLCHAIN: ${{ matrix.toolchain }} + run: ./build.sh + + - name: Upload library artifacts + uses: actions/upload-artifact@v2 + with: + name: library-${{ runner.os }} + path: target/release/${{ matrix.lib }} + + build-py: + name: Build Python + needs: [build-manylinux, build-other] + + strategy: + matrix: + plat: [Linux, macOS, Windows] + python-version: [3.6] + include: + - plat: Linux + plat-name: manylinux2014_x86_64 + - plat: macOS + plat-name: macosx_10_9_x86_64 # macosx_10_9_universal2 + - plat: Windows + plat-name: win32 + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine auditwheel + + - name: Fetch library artifacts + uses: actions/download-artifact@v2 + with: + name: library-${{ matrix.plat }} + path: wrappers/python/indy_credx/ + + - name: Build python packages + run: | + python setup.py bdist_wheel --python-tag=py3 --plat-name=${{ matrix.plat-name }} + working-directory: wrappers/python + + - if: "matrix.plat == 'Linux'" + run: auditwheel show wrappers/python/dist/* + + - name: Upload python artifacts + uses: actions/upload-artifact@v2 + with: + name: python-${{ matrix.plat }} + path: wrappers/python/dist/* diff --git a/.github/workflows/rusttest.yml b/.github/workflows/rusttest.yml index 02b23d6..67f99e5 100644 --- a/.github/workflows/rusttest.yml +++ b/.github/workflows/rusttest.yml @@ -1,17 +1,21 @@ -name: "Unit Tests" +name: "Run Tests" on: push: - branches: - - main + branches: [main] pull_request: - branches: - - main + branches: [main] jobs: - lints: - name: Lints - runs-on: ubuntu-latest + test: + name: Test Suite + + strategy: + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + + runs-on: ${{ matrix.os }} + steps: - name: Checkout sources uses: actions/checkout@v2 @@ -21,33 +25,26 @@ jobs: with: profile: minimal toolchain: stable - override: true - components: rustfmt - - name: Run cargo fmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - name: Cache cargo resources + uses: Swatinem/rust-cache@v1 - - name: Run cargo check + - name: Cargo check uses: actions-rs/cargo@v1 with: command: check - test: - name: Test Suite - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v2 + - name: Cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check - - name: Install stable toolchain - uses: actions-rs/toolchain@v1 + - name: Debug build + uses: actions-rs/cargo@v1 with: - profile: minimal - toolchain: stable - override: true + command: build + args: --all-targets - name: Test default features uses: actions-rs/cargo@v1 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..91ca4c4 --- /dev/null +++ b/build.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +# NOTE: +# MacOS universal build currently requires MacOS 11 (Big Sur) for the appropriate SDK, +# and `sudo xcode-select --install` must be run to install the command line utilities. +# Rust's `beta` channel must be installed because aarch64 is still a tier-2 target: +# `rustup toolchain install beta`. +# The build command becomes `BUILD_TARGET=apple-darwin BUILD_TOOLCHAIN=beta ./build.sh` + +RUSTUP=${RUSTUP:-`command -v rustup`} +PROJECT=indy-credx +LIB_NAME=indy_credx + +if [ ! -x "$RUSTUP" ]; then + echo "rustup command not found: it can be obtained from https://rustup.rs/" + exit 1 +fi + +TOOLCHAIN=`$RUSTUP default` +TARGET="${BUILD_TARGET-}" + +if [ -z "$BUILD_TOOLCHAIN" ]; then + BUILD_TOOLCHAIN=${TOOLCHAIN%%-*} + if [ -z "$BUILD_TOOLCHAIN" ]; then + echo "Error: Could not determine default Rust toolchain" + exit 1 + fi +fi + +MACOS_UNIVERSAL_TARGETS="aarch64-apple-darwin x86_64-apple-darwin" + +# Fail on any execution errors +set -e + +if [ "$TARGET" = "apple-darwin" ]; then + # MacOS universal build + INSTALLED_TARGETS=`$RUSTUP +$BUILD_TOOLCHAIN target list --installed` + # Install target(s) as needed + echo "Checking install targets for MacOS universal build .." + for target in $MACOS_UNIVERSAL_TARGETS; do + if ! `echo "$INSTALLED_TARGETS" | grep -q $target`; then + $RUSTUP +$BUILD_TOOLCHAIN target add $target + fi + done +elif [ -z "$TARGET" ]; then + case "$TOOLCHAIN" in + *apple-darwin*) + # Check if the required targets for a universal build are installed + INSTALLED_TARGETS=`$RUSTUP +$BUILD_TOOLCHAIN target list --installed` + TARGET="apple-darwin" + for target in $MACOS_UNIVERSAL_TARGETS; do + if ! `echo "$INSTALLED_TARGETS" | grep -q $target`; then + TARGET= + break + fi + done + if [ "$TARGET" = "apple-darwin" ]; then + echo "Automatically enabled MacOS universal build" + else + echo "Universal MacOS build not enabled" + fi + esac +fi + +if [ "$TARGET" = "apple-darwin" ]; then + MAJOR_VER=`sw_vers | grep ProductVersion | cut -f 2 | cut -f 1 -d .` + if [ "$MAJOR_VER" -lt 11 ]; then + echo "MacOS universal build requires OS 11 (Big Sur) or newer" + TARGET= + fi +fi + +if [ "$TARGET" = "apple-darwin" ]; then + # Build both targets and combine them into a universal library with `lipo` + TARGET_LIBS= + for target in $MACOS_UNIVERSAL_TARGETS; do + echo "Building $PROJECT for toolchain '$BUILD_TOOLCHAIN', target '$target'.." + $RUSTUP run $BUILD_TOOLCHAIN cargo build --release --target $target + TARGET_LIBS="./target/$target/release/lib${LIB_NAME}.dylib $TARGET_LIBS" + done + + mkdir -p ./target/release + OUTPUT="./target/release/lib${LIB_NAME}.dylib" + echo "Combining targets into universal library" + lipo -create -output $OUTPUT $TARGET_LIBS +else + # Build normal target + echo "Building $PROJECT for toolchain '$BUILD_TOOLCHAIN'.." + CMD="$RUSTUP run $BUILD_TOOLCHAIN cargo build --release" + if [ -n "$TARGET" ]; then + $CMD --target "$TARGET" + else + $CMD + fi +fi From e4f013d73f7db6366b4bf6458f199e438f88e075 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Tue, 2 Feb 2021 12:12:10 -0800 Subject: [PATCH 2/4] build vendored openssl Signed-off-by: Andrew Whitehead --- .github/workflows/build.yml | 2 ++ .github/workflows/rusttest.yml | 50 ++++++++++++++++++++++++++-------- build.sh | 5 ++-- indy-credx/Cargo.toml | 1 + indy-data-types/Cargo.toml | 2 ++ 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbeda1b..a1d5c4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,6 +35,7 @@ jobs: - name: Build library env: + BUILD_FEATURES: vendored BUILD_TARGET: ${{ matrix.target }} run: ./build.sh @@ -75,6 +76,7 @@ jobs: - name: Build library env: + BUILD_FEATURES: vendored BUILD_TARGET: ${{ matrix.target }} BUILD_TOOLCHAIN: ${{ matrix.toolchain }} run: ./build.sh diff --git a/.github/workflows/rusttest.yml b/.github/workflows/rusttest.yml index 67f99e5..dd2b7f4 100644 --- a/.github/workflows/rusttest.yml +++ b/.github/workflows/rusttest.yml @@ -7,14 +7,10 @@ on: branches: [main] jobs: - test: - name: Test Suite + lints: + name: Lints - strategy: - matrix: - os: [macos-latest, windows-latest, ubuntu-latest] - - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest steps: - name: Checkout sources @@ -40,25 +36,55 @@ jobs: command: fmt args: --all -- --check + test: + name: Test Suite + needs: [lints] + + strategy: + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + + - name: Cache cargo resources + uses: Swatinem/rust-cache@v1 + - name: Debug build uses: actions-rs/cargo@v1 with: command: build - args: --all-targets + args: --manifest-path indy-credx/Cargo.toml --features vendored - - name: Test default features + - name: Test indy-utils uses: actions-rs/cargo@v1 with: command: test + args: --manifest-path indy-utils/Cargo.toml - - name: Test CL + - name: Test indy-data-types (CL) uses: actions-rs/cargo@v1 with: command: test args: --manifest-path indy-data-types/Cargo.toml --features cl - - name: Test CL-native + - name: Test indy-data-types (CL-native) + uses: actions-rs/cargo@v1 + with: + command: test + args: --manifest-path indy-data-types/Cargo.toml --features cl_native,vendored + + - name: Test indy-credx (vendored) uses: actions-rs/cargo@v1 with: command: test - args: --manifest-path indy-data-types/Cargo.toml --features cl_native + args: --manifest-path indy-credx/Cargo.toml --features vendored diff --git a/build.sh b/build.sh index 91ca4c4..8955f32 100755 --- a/build.sh +++ b/build.sh @@ -10,6 +10,7 @@ RUSTUP=${RUSTUP:-`command -v rustup`} PROJECT=indy-credx LIB_NAME=indy_credx +FEATURES="${BUILD_FEATURES:-default}" if [ ! -x "$RUSTUP" ]; then echo "rustup command not found: it can be obtained from https://rustup.rs/" @@ -75,7 +76,7 @@ if [ "$TARGET" = "apple-darwin" ]; then TARGET_LIBS= for target in $MACOS_UNIVERSAL_TARGETS; do echo "Building $PROJECT for toolchain '$BUILD_TOOLCHAIN', target '$target'.." - $RUSTUP run $BUILD_TOOLCHAIN cargo build --release --target $target + $RUSTUP run $BUILD_TOOLCHAIN cargo build --manifest-path indy-credx/Cargo.toml --release --features $FEATURES --target $target TARGET_LIBS="./target/$target/release/lib${LIB_NAME}.dylib $TARGET_LIBS" done @@ -86,7 +87,7 @@ if [ "$TARGET" = "apple-darwin" ]; then else # Build normal target echo "Building $PROJECT for toolchain '$BUILD_TOOLCHAIN'.." - CMD="$RUSTUP run $BUILD_TOOLCHAIN cargo build --release" + CMD="$RUSTUP run $BUILD_TOOLCHAIN cargo build --manifest-path indy-credx/Cargo.toml --release --features $FEATURES" if [ -n "$TARGET" ]; then $CMD --target "$TARGET" else diff --git a/indy-credx/Cargo.toml b/indy-credx/Cargo.toml index f7203b7..b08b864 100644 --- a/indy-credx/Cargo.toml +++ b/indy-credx/Cargo.toml @@ -19,6 +19,7 @@ crate-type = ["staticlib", "rlib", "cdylib"] default = ["ffi"] ffi = ["ffi-support", "logger", "zeroize"] logger = ["env_logger"] +vendored = ["indy-data-types/vendored"] [dependencies] env_logger = { version = "0.7.1", optional = true } diff --git a/indy-data-types/Cargo.toml b/indy-data-types/Cargo.toml index 4550987..7f5a58e 100644 --- a/indy-data-types/Cargo.toml +++ b/indy-data-types/Cargo.toml @@ -23,8 +23,10 @@ hash = ["indy-utils/hash"] merkle_tree = ["hash"] rich_schema = [] serde_support = ["indy-utils/serde_support", "serde", "serde_json"] +vendored = ["openssl", "openssl/vendored"] [dependencies] +openssl = { version = "0.10", optional = true } once_cell = "1.4" regex = "1.3" serde = { version = "1.0", optional = true, features = ["derive"] } From d54c94db951e059057751a3cbb218b4f69165266 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Tue, 2 Feb 2021 13:25:14 -0800 Subject: [PATCH 3/4] test build script, python package Signed-off-by: Andrew Whitehead --- .github/workflows/build.yml | 53 +++++++++++++++++++---------- .gitignore | 1 + wrappers/python/demo/test.py | 64 ++++++++++++++++++++---------------- 3 files changed, 71 insertions(+), 47 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a1d5c4d..626ae89 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,10 +1,6 @@ name: "Build Packages" -on: workflow_dispatch - -defaults: - run: - shell: bash +"on": push jobs: build-manylinux: @@ -37,7 +33,7 @@ jobs: env: BUILD_FEATURES: vendored BUILD_TARGET: ${{ matrix.target }} - run: ./build.sh + run: sh ./build.sh - name: Upload library artifacts uses: actions/upload-artifact@v2 @@ -74,12 +70,24 @@ jobs: - name: Cache cargo resources uses: Swatinem/rust-cache@v1 + # pre-build so that openssl dependency is cached, otherwise it will complain: + # "This perl implementation doesn't produce Windows like paths" + - if: "runner.os == 'Windows'" + name: Pre-build (Windows) + uses: actions-rs/cargo@v1 + env: + OPENSSL_STATIC: 1 + with: + command: build + args: --release --manifest-path indy-credx/Cargo.toml --features vendored + - name: Build library env: BUILD_FEATURES: vendored BUILD_TARGET: ${{ matrix.target }} BUILD_TOOLCHAIN: ${{ matrix.toolchain }} - run: ./build.sh + OPENSSL_STATIC: 1 + run: sh ./build.sh - name: Upload library artifacts uses: actions/upload-artifact@v2 @@ -93,17 +101,17 @@ jobs: strategy: matrix: - plat: [Linux, macOS, Windows] + os: [ubuntu-latest, macos-latest, windows-latest] python-version: [3.6] include: - - plat: Linux + - os: ubuntu-latest plat-name: manylinux2014_x86_64 - - plat: macOS + - os: macos-latest plat-name: macosx_10_9_x86_64 # macosx_10_9_universal2 - - plat: Windows - plat-name: win32 + - os: windows-latest + plat-name: win_amd64 - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} steps: - name: Checkout @@ -122,19 +130,28 @@ jobs: - name: Fetch library artifacts uses: actions/download-artifact@v2 with: - name: library-${{ matrix.plat }} + name: library-${{ runner.os }} path: wrappers/python/indy_credx/ - - name: Build python packages + - name: Build python package run: | python setup.py bdist_wheel --python-tag=py3 --plat-name=${{ matrix.plat-name }} working-directory: wrappers/python - - if: "matrix.plat == 'Linux'" + - name: Test python package + shell: sh + run: | + cd wrappers/python + pip install --upgrade pip + pip install dist/* + python -m demo.test + + - if: "runner.os == 'Linux'" + name: Auditwheel run: auditwheel show wrappers/python/dist/* - - name: Upload python artifacts + - name: Upload python package uses: actions/upload-artifact@v2 with: - name: python-${{ matrix.plat }} + name: python-${{ runner.os }} path: wrappers/python/dist/* diff --git a/.gitignore b/.gitignore index a9d37c5..8094f6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.vscode target Cargo.lock diff --git a/wrappers/python/demo/test.py b/wrappers/python/demo/test.py index 9ff2ff8..b0d4aae 100644 --- a/wrappers/python/demo/test.py +++ b/wrappers/python/demo/test.py @@ -20,12 +20,20 @@ test_did = "55GkHamhTU1ZbTbV2ab9DE" schema = Schema.create(test_did, "schema name", "schema version", ["attr"], seq_no=15) -print(schema.to_dict()) +assert schema.to_dict() == { + "ver": "1.0", + "id": f"{test_did}:2:schema name:schema version", + "name": "schema name", + "version": "schema version", + "attrNames": ["attr"], + "seqNo": 15, +} + cred_def, cred_def_pvt, key_proof = CredentialDefinition.create( test_did, schema, "CL", tag="tag", support_revocation=True ) -print(cred_def) +assert cred_def.id == f"{test_did}:3:CL:15:tag" ( rev_reg_def, @@ -33,20 +41,20 @@ rev_reg, rev_reg_init_delta, ) = RevocationRegistryDefinition.create(test_did, cred_def, "default", "CL_ACCUM", 100) -print("Tails file hash:", rev_reg_def.tails_hash) +# print("Tails file hash:", rev_reg_def.tails_hash) master_secret = MasterSecret.create() master_secret_id = "my id" cred_offer = CredentialOffer.create(schema.id, cred_def, key_proof) -print("Credential offer:") -print(cred_offer.to_json()) +# print("Credential offer:") +# print(cred_offer.to_json()) cred_req, cred_req_metadata = CredentialRequest.create( test_did, cred_def, master_secret, master_secret_id, cred_offer ) -print("Credential request:") -print(cred_req.to_json()) +# print("Credential request:") +# print(cred_req.to_json()) issuer_rev_index = 1 @@ -66,12 +74,12 @@ rev_reg_def.tails_location, ), ) -print("Issued credential:") -print(cred.to_json()) +# print("Issued credential:") +# print(cred.to_json()) cred_received = cred.process(cred_req_metadata, master_secret, cred_def, rev_reg_def) -print("Processed credential:") -print(cred_received.to_json()) +# print("Processed credential:") +# print(cred_received.to_json()) timestamp = int(time()) @@ -111,16 +119,14 @@ ) # print(presentation.to_json()) -print( - "Verified:", - presentation.verify( - pres_req, - [schema], - [cred_def], - [rev_reg_def], - {rev_reg_def.id: {timestamp: rev_reg}}, - ), +verified = presentation.verify( + pres_req, + [schema], + [cred_def], + [rev_reg_def], + {rev_reg_def.id: {timestamp: rev_reg}}, ) +assert verified # rev_delta_2 = rev_reg.revoke_credential( @@ -142,13 +148,13 @@ pres_req, present_creds, {}, master_secret, [schema], [cred_def] ) -print( - "Verified:", - presentation.verify( - pres_req, - [schema], - [cred_def], - [rev_reg_def], - {rev_reg_def.id: {timestamp: rev_reg}}, - ), +verified = presentation.verify( + pres_req, + [schema], + [cred_def], + [rev_reg_def], + {rev_reg_def.id: {timestamp: rev_reg}}, ) +assert not verified + +print("ok") From edb0cd1e6c392f724903966b0e997adfeb200a77 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 18 Feb 2021 15:11:08 -0800 Subject: [PATCH 4/4] publish python package Signed-off-by: Andrew Whitehead --- .github/workflows/build.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 626ae89..68ce6ba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,14 @@ name: "Build Packages" -"on": push +"on": + release: + types: [created] + workflow_dispatch: + inputs: + publish: + description: "Publish packages" + required: true + default: "false" jobs: build-manylinux: @@ -155,3 +163,14 @@ jobs: with: name: python-${{ runner.os }} path: wrappers/python/dist/* + + - if: | + (github.event_name == 'release' || + (github.event_name == 'workflow_dispatch' && + github.event.inputs.publish == 'true')) + name: Publish python package + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + twine upload --skip-existing wrappers/python/dist/*