lssa/.github/docker/ci.Dockerfile
jonesmarvin8 914f14e870
refactor(keycard_wallet): replace keycard-py with keycard-rs (#595)
* refactor(keycard_wallet): replace keycard-py (pyo3) with native keycard-rs

Rewrites the Keycard integration to talk to the LEE-flavored applet
directly from Rust via keycard-rs (pinned git dependency), dropping the
pyo3 shim, python_path.rs, and the vendored keycard-py Python library
entirely. Verified end-to-end against real hardware: pairing, PIN
verification, mnemonic loading, BIP340 Schnorr signing, and transfers
between keycard and public/private accounts.

Also cleans up the pyo3 usage that had leaked into wallet's signing
path (signing.rs, account_manager.rs) beyond the keycard CLI itself,
and trims wallet_with_keycard.sh's Python setup down to just pyscard,
which is only needed by the force_unpower.py test helper now.

* Updated to v2 secure communication

* ci: install libpcsclite-dev for pcsc crate builds

* docs(keycard): clarify personalization is mandatory and document default CA

Reinstalling the applet via `./gradlew install` wipes any existing
personalization regardless of firmware source, which wasn't previously
called out and is a common source of "card not available" confusion.
Also state plainly that personalization is required before any command
works, and document keycard-rs's actual baked-in default CA public key
instead of only describing the override mechanism.

Export KEYCARD_CA_PUBLIC_KEY in all keycard test scripts so they work
against the dev/test-CA personalization flow they rely on.

* fix(keycard): address PR #595 review comments

- Propagate the load_mnemonic error instead of swallowing it behind
  is_ok(), matching every other command handler in this file.
- Add deny.toml allowing the keycard-rs git source, fixing the
  source-not-allowed failure in `cargo deny check`. Licenses and
  advisories checks still have pre-existing, separate failures not
  addressed here.
- Drop the pinned rev for the keycard-rs git dependency so it tracks
  the upstream default branch instead.

* chore(deny): trim deny.toml to essentials and allow all in-use licenses

Replace the full cargo-deny init template with just the two sections
that matter: the keycard-rs git-source allowance, and an explicit
license allow-list covering every license currently in the dependency
tree. cargo deny check now passes on sources, bans, and licenses;
advisories still fails on a pre-existing, unrelated RUSTSEC advisory.

* fix(deny): remove second config and add source to the original one

* chore: pin keycard-rs dependency and fix factory-reset debug-gate doc

* chore: regenerate test fixture and lockfile after rebase onto dev

---------

Co-authored-by: Daniil Polyakov <arjentix@gmail.com>
2026-07-23 15:50:30 -04:00

99 lines
4.1 KiB
Docker

# Image behind the `container:` of the CI jobs. Everything the jobs used to
# install per-run is baked in here instead, so a CI run no longer asks the risc0
# install servers for anything.
#
# The image tag is a hash of this file plus rust-toolchain.toml, so editing
# either rebuilds the image on the PR that changes it. See ci-image.yml.
#
# Keep the base tag in sync with rust-toolchain.toml.
FROM rust:1.94.0-trixie
# GitHub sets HOME=/github/home inside container jobs, which hides anything we
# bake into the image's ~. rzup defaults to $HOME/.risc0, so pin it to a fixed
# path; RUSTUP_HOME and CARGO_HOME already point at /usr/local from the base
# image, and rzup honours all three.
ENV RISC0_HOME=/usr/local/risc0
ENV PATH=/usr/local/risc0/bin:$PATH
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
clang \
libclang-dev \
libssl-dev \
pkg-config \
libpcsclite-dev \
curl \
git \
jq \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
# The runner pre-creates the workspace as another uid, so git in a container job
# calls it dubious. checkout's own fix is --global, which only holds while HOME
# still points at the gitconfig it wrote; --system holds regardless.
RUN git config --system --add safe.directory '*'
# The base image already has this toolchain at the minimal profile, so the
# `profile = "default"` in rust-toolchain.toml is a no-op here: rustup sees the
# toolchain as installed and never applies it. Add what the jobs need by hand.
COPY rust-toolchain.toml /tmp/toolchain/rust-toolchain.toml
RUN cd /tmp/toolchain \
&& rustup toolchain install \
&& rustup component add clippy rustfmt \
&& rm -rf /tmp/toolchain
# For `cargo +nightly fmt` in the fmt-rs job.
RUN rustup toolchain install nightly --profile minimal --component rustfmt
# The bootstrap script only ever drops rzup in $HOME/.risc0/bin, so run it
# against the build-time HOME and keep just the binary. rzup itself then honours
# RISC0_HOME and installs each component under /usr/local.
#
# Versions pinned to the set currently validated in local dev (`rzup show`);
# bare `rzup install` would float all four default components to latest. r0vm
# and cargo-risczero track each other and the risc0-zkvm crate version.
RUN curl -L https://risczero.com/install | bash \
&& mv /root/.risc0/bin/rzup /usr/local/bin/rzup \
&& rm -rf /root/.risc0 \
&& rzup install rust 1.94.1 \
&& rzup install cpp 2024.1.5 \
&& rzup install r0vm 3.0.5 \
&& rzup install cargo-risczero 3.0.5
# Copying docker. Static Go binaries, so the alpine-built ones run fine here.
COPY --from=docker:29.6.1-cli /usr/local/bin/docker /usr/local/bin/docker
COPY --from=docker:29.6.1-cli /usr/local/libexec/docker/cli-plugins/docker-compose \
/usr/local/libexec/docker/cli-plugins/docker-compose
COPY --from=docker:29.6.1-cli /usr/local/libexec/docker/cli-plugins/docker-buildx \
/usr/local/libexec/docker/cli-plugins/docker-buildx
# Prebuilt binaries; compiling these from source would dominate the image build.
# Versions pinned so a rebuild of the same image ships the same tools.
ENV BINSTALL_VERSION=1.21.0
RUN curl -L --proto '=https' --tlsv1.2 -sSf \
https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash \
&& cargo binstall --no-confirm \
cargo-nextest@0.9.140 \
taplo-cli@0.10.0 \
cargo-machete@0.9.2 \
cargo-deny@0.20.2 \
just@1.56.0
# Smoke-test every tool the jobs use. A bad install should fail here, not later
# in some CI job that reuses this cached image. pyo3's `auto-initialize` links
# libpython, and the base image ships python3 without it, so check the .so too.
RUN cargo --version \
&& cargo +nightly fmt --version \
&& cargo clippy --version \
&& ls /usr/lib/*/libpython3*.so \
&& r0vm --version \
&& cargo risczero --version \
&& cargo nextest --version \
&& taplo --version \
&& cargo machete --version \
&& cargo deny --version \
&& just --version \
&& docker --version \
&& docker compose version \
&& docker buildx version