Skip to content

Merge pull request #643 from zcash/wallet-db-hardening #1546

Merge pull request #643 from zcash/wallet-db-hardening

Merge pull request #643 from zcash/wallet-db-hardening #1546

Workflow file for this run

name: CI
on:
pull_request:
push:
branches: main
merge_group:
permissions: {}
jobs:
test-msrv-required:
name: Test ${{ matrix.state }} on ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
target:
- Linux
state:
- default
include:
- target: Linux
os: ubuntu-latest
env:
RUSTFLAGS: ${{ matrix.rustflags }}
RUSTDOCFLAGS: ${{ matrix.rustflags }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Each chain backend lives in its own workspace with its own lockfile
# (zcash/zallet#540), so each is tested separately alongside the shared
# zallet-core workspace.
#
# The lockfiles may deliberately diverge on the zebra-*/zaino-* trees,
# but crates touching the shared wallet database must stay in lockstep.
- name: Check wallet-critical dependency lockstep
run: ./utils/check-lockstep.sh
# Exercise the lockfile-sync helper end to end: it regenerates every
# workspace lockfile from its manifest, so on an in-lockstep tree it must be
# a no-op. A non-empty diff means the committed lockfiles drifted from what
# the manifests resolve to.
- name: Verify workspace lockfiles are in sync with the manifests
run: |
./utils/sync-lockfiles.sh
git diff --exit-code
- name: Run tests (zallet-core)
run: >
cargo test
--workspace
--features zcashd-import,rpc-cli,tokio-console
- name: Run tests (zaino backend)
run: >
cargo test
--manifest-path backends/zaino/Cargo.toml
--features zcashd-import,rpc-cli,tokio-console
- name: Run tests (zebra-state backend)
run: >
cargo test
--manifest-path backends/zebra/Cargo.toml
--features zcashd-import,rpc-cli,tokio-console
# End-to-end check of the `zallet` launcher: config-driven dispatch to the
# backend binaries, and the backend binaries' own backend-key validation.
- name: Launcher dispatch smoke test
run: |
cargo build --bin zallet
cargo build --manifest-path backends/zebra/Cargo.toml --bin zallet-zebra
cargo build --manifest-path backends/zaino/Cargo.toml --bin zallet-zaino
bindir="$(mktemp -d)"
datadir="$(mktemp -d)"
cp target/debug/zallet "$bindir/"
cp backends/zebra/target/debug/zallet-zebra "$bindir/"
# No config file: the launcher dispatches to the default (zebra-state)
# backend, passing arguments through.
"$bindir/zallet" --datadir "$datadir" --version
# Generate a real config through the launcher (also exercises subcommand
# and flag passthrough), then point it at the zaino backend. The key must
# be prepended: top-level TOML keys precede the first [section] header.
"$bindir/zallet" --datadir "$datadir" example-config \
-o "$datadir/zallet.toml" \
--this-is-beta-code-and-you-will-need-to-recreate-the-example-later
sed -i '1i backend = "zaino"' "$datadir/zallet.toml"
# backend = "zaino" maps to the zallet-zaino binary: with the binary
# absent, the launcher must fail and name what it looked for.
if out=$("$bindir/zallet" --datadir "$datadir" --version 2>&1); then
echo "expected dispatch to a missing zallet-zaino to fail"; exit 1
fi
echo "$out" | grep -q "zallet-zaino" || { echo "error did not name zallet-zaino: $out"; exit 1; }
# With the binary present, the same invocation succeeds.
cp backends/zaino/target/debug/zallet-zaino "$bindir/"
"$bindir/zallet" --datadir "$datadir" --version
# Belt-and-braces: a backend binary invoked directly against a config
# that names the other backend refuses to run.
if out=$("$bindir/zallet-zebra" --datadir "$datadir" example-config -o - \
--this-is-beta-code-and-you-will-need-to-recreate-the-example-later 2>&1); then
echo "expected zallet-zebra to reject a backend=zaino config"; exit 1
fi
echo "$out" | grep -q "provides the 'zebra' backend" \
|| { echo "unexpected mismatch error: $out"; exit 1; }
- name: Verify working directory is clean
run: git diff --exit-code
test-msrv:
name: Test ${{ matrix.state }} on ${{ matrix.target }}
runs-on: ${{ matrix.os }}
continue-on-error: true
strategy:
matrix:
target:
- macOS
- Windows
state:
- default
- NU7
include:
- target: macOS
os: macOS-latest
- target: Windows
os: windows-latest
- target: Linux
state: NU7
os: ubuntu-latest
rustflags: '--cfg zcash_unstable="nu7"'
- target: Linux
state: merchant_terminal
os: ubuntu-latest
rustflags: '--cfg zallet_build="merchant_terminal"'
exclude:
- target: macOS
state: NU7
env:
RUSTFLAGS: ${{ matrix.rustflags }}
RUSTDOCFLAGS: ${{ matrix.rustflags }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Cross-platform / NU7 / merchant_terminal coverage tracks zallet-core and the
# zaino backend; the `zebra-state` backend is Linux-only and covered by
# `test-msrv-required`.
- name: Run tests (zallet-core)
run: >
cargo test
--workspace
--features zcashd-import,rpc-cli,tokio-console
- name: Run tests (zaino backend)
run: >
cargo test
--manifest-path backends/zaino/Cargo.toml
--features zcashd-import,rpc-cli,tokio-console
- name: Verify working directory is clean
run: git diff --exit-code
build-latest:
name: Latest build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
id: toolchain
- run: rustup override set ${RUST_TOOLCHAIN}
shell: bash
env:
RUST_TOOLCHAIN: ${{steps.toolchain.outputs.name}}
- name: Remove lockfiles to build with latest dependencies
# Multi-path rm requires bash: the Windows default shell (pwsh) aliases
# `rm` to Remove-Item, which rejects multiple positional paths.
shell: bash
run: rm Cargo.lock backends/zebra/Cargo.lock backends/zaino/Cargo.lock
- name: Build crates (zallet-core)
run: >
cargo build
--workspace
--all-targets
--features zcashd-import,rpc-cli,tokio-console
- name: Build crates (zaino backend)
run: >
cargo build
--manifest-path backends/zaino/Cargo.toml
--all-targets
--features zcashd-import,rpc-cli,tokio-console
- name: Build crates (zebra-state backend)
if: runner.os == 'Linux'
run: >
cargo build
--manifest-path backends/zebra/Cargo.toml
--all-targets
--features zcashd-import,rpc-cli,tokio-console
- name: Verify working directory is clean (excluding lockfiles)
# The `--` is load-bearing: the deleted lockfiles are not regenerated on
# platforms that skip a backend build, and git fatals on a pathspec for
# a nonexistent path unless the paths are `--`-separated.
run: git diff --exit-code -- ':!Cargo.lock' ':!backends/zebra/Cargo.lock' ':!backends/zaino/Cargo.lock'
trigger-integration:
name: Trigger integration tests
runs-on: ubuntu-latest
steps:
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-id: ${{ secrets.DISPATCH_APP_ID }}
private-key: ${{ secrets.DISPATCH_APP_PRIVATE_KEY }}
owner: zcash
repositories: integration-tests
- name: Get requested test branch, if any
id: test-branch
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
TEST_SHA=$(gh pr -R zcash/zallet list --search "${HEAD_SHA}" --json body | jq '.[0].body' | sed '/[^ ]ZIT-Revision/!d' | sed -E 's/.*ZIT-Revision: ([^\\]*)\\.*/\1/')
echo "test_sha=${TEST_SHA}" >> $GITHUB_OUTPUT
- name: Trigger integration tests
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
TEST_SHA: ${{ steps.test-branch.outputs.test_sha }}
run: >
gh api repos/zcash/integration-tests/dispatches
--field event_type="zallet-interop-request"
--field client_payload[sha]="$GITHUB_SHA"
--field client_payload[test_sha]="${TEST_SHA}"
required-checks:
name: Required status checks have passed
needs:
- test-msrv-required
- build-latest
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Determine whether all required-pass steps succeeded
run: |
echo '${{ toJSON(needs) }}' | jq -e '[ .[] | .result == "success" ] | all'