From 843d3d4a6d5ed060f33d592fbc492e23cc6bb4b0 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 00:30:05 -0500 Subject: [PATCH 01/26] add build.sh, compat.sh --- build.sh | 32 ++++++++++++++++++++++ compat.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100755 build.sh create mode 100755 compat.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5452e23 --- /dev/null +++ b/build.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e + +DIR="$( cd "$( dirname "$0" )" && pwd )" +REPO_ROOT="$(git rev-parse --show-toplevel)" +PLATFORM="linux/amd64" +OCI_OUTPUT="$REPO_ROOT/build/oci" +DOCKERFILE="$REPO_ROOT/Dockerfile" +NAME=zcash-devtool + +export DOCKER_BUILDKIT=1 +export SOURCE_DATE_EPOCH=1 + +echo $DOCKERFILE +mkdir -p $OCI_OUTPUT + +# Build runtime image for docker run +echo "Building runtime image..." +docker build -f "$DOCKERFILE" "$REPO_ROOT" \ + --platform "$PLATFORM" \ + --target runtime \ + --output type=oci,rewrite-timestamp=true,force-compression=true,dest=$OCI_OUTPUT/zcash-devtool.tar,name=zcash-devtool \ + "$@" + +# Extract from export stage +echo "Extracting binaries..." +docker build -f "$DOCKERFILE" "$REPO_ROOT" --quiet \ + --platform "$PLATFORM" \ + --target export \ + --output type=local,dest="$REPO_ROOT/build" \ + "$@" diff --git a/compat.sh b/compat.sh new file mode 100755 index 0000000..43d6ecb --- /dev/null +++ b/compat.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +set -e +readonly MIN_BASH_VERSION=5 +readonly MIN_DOCKER_VERSION=26.0.0 +readonly MIN_BUILDX_VERSION=0.13 +### Exit with error message +die() { + echo "$@" >&2 + exit 1 +} +### Bail and instruct user on missing package to install for their platform +die_pkg() { + local -r package=${1?} + local -r version=${2?} + local install_cmd + case "$OSTYPE" in + linux*) + if command -v "apt" >/dev/null; then + install_cmd="apt install ${package}" + elif command -v "yum" >/dev/null; then + install_cmd="yum install ${package}" + elif command -v "pacman" >/dev/null; then + install_cmd="pacman -Ss ${package}" + elif command -v "emerge" >/dev/null; then + install_cmd="emerge ${package}" + elif command -v "nix-env" >/dev/null; then + install_cmd="nix-env -i ${package}" + fi + ;; + bsd*) install_cmd="pkg install ${package}" ;; + darwin*) install_cmd="port install ${package}" ;; + *) die "Error: Your operating system is not supported" ;; + esac + echo "Error: ${package} ${version}+ does not appear to be installed." >&2 + [ -n "$install_cmd" ] && echo "Try: \`${install_cmd}\`" >&2 + exit 1 +} +### Check if actual binary version is >= minimum version +check_version(){ + local pkg="${1?}" + local have="${2?}" + local need="${3?}" + local i ver1 ver2 IFS='.' + [[ "$have" == "$need" ]] && return 0 + read -r -a ver1 <<< "$have" + read -r -a ver2 <<< "$need" + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); + do ver1[i]=0; + done + for ((i=0; i<${#ver1[@]}; i++)); do + [[ -z ${ver2[i]} ]] && ver2[i]=0 + ((10#${ver1[i]} > 10#${ver2[i]})) && return 0 + ((10#${ver1[i]} < 10#${ver2[i]})) && die_pkg "${pkg}" "${need}" + done +} +### Check if required binaries are installed at appropriate versions +check_tools(){ + if [ -z "${BASH_VERSINFO[0]}" ] \ + || [ "${BASH_VERSINFO[0]}" -lt "${MIN_BASH_VERSION}" ]; then + die_pkg "bash" "${MIN_BASH_VERSION}" + fi + for cmd in "$@"; do + case $cmd in + buildx) + docker buildx version >/dev/null 2>&1 || die "Error: buildx not found" + version=$(docker buildx version 2>/dev/null | grep -o 'v[0-9.]*' | sed 's/v//') + check_version "buildx" "${version}" "${MIN_BUILDX_VERSION}" + ;; + docker) + command -v docker >/dev/null || die "Error: docker not found" + version=$(docker version -f '{{ .Server.Version }}') + check_version "docker" "${version}" "${MIN_DOCKER_VERSION}" + ;; + esac + done +} +check_tools docker buildx; +docker info -f '{{ .DriverStatus }}' \ + | grep "io.containerd.snapshotter.v1" >/dev/null \ +|| die "Error: Docker Engine is not using containerd for image storage" + + From 72fe62158fd3dc714de20261eff53339ba54f1a9 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 00:30:33 -0500 Subject: [PATCH 02/26] add Dockerfile, building --- Dockerfile | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b6cdbe7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,145 @@ +# syntax=docker/dockerfile:1 + +# stages: +# - setup: sets default values +# - release: builds release binaries +# - runtime: prepares the release image +# +# We first set default values for build arguments used across the stages. +# Each stage must define the build arguments (ARGs) it uses. + +ARG RUST_VERSION=1.91.1 + +ARG FEATURES="" + +ARG UID=10801 +ARG GID=${UID} +ARG USER="devtool-user" +ARG HOME="/home/${USER}" +ARG CARGO_HOME="${HOME}/.cargo" +ARG CARGO_TARGET_DIR="${HOME}/target" +ARG TARGET_ARCH="x86_64-unknown-linux-musl" + +FROM stagex/core-busybox@sha256:d608daa946e4799cf28b105aba461db00187657bd55ea7c2935ff11dac237e27 AS busybox +FROM stagex/pallet-rust@sha256:4062550919db682ebaeea07661551b5b89b3921e3f3a2b0bc665ddea7f6af1ca AS pallet-rust + +# This stage captures build args as env vars +FROM pallet-rust AS setup + +SHELL ["/bin/sh", "-xo", "pipefail", "-c"] + +# Build arguments and variables +ARG CARGO_INCREMENTAL +# default to 0, disables incremental compilation. +ENV CARGO_INCREMENTAL=${CARGO_INCREMENTAL:-0} + +ARG CARGO_HOME +ENV CARGO_HOME=${CARGO_HOME} + +ARG FEATURES +ENV FEATURES=${FEATURES} + +# This stage builds the zcash-devtool release binary. +FROM setup AS release + +ARG HOME +WORKDIR ${HOME} + +ARG CARGO_HOME +ARG CARGO_TARGET_DIR +ARG TARGET_ARCH + +ENV RUST_BACKTRACE=1 +ENV RUSTFLAGS="-C codegen-units=1" +ENV RUSTFLAGS="${RUSTFLAGS} -C target-feature=+crt-static" +ENV RUSTFLAGS="${RUSTFLAGS} -C link-arg=-Wl,--build-id=none" + +ENV SOURCE_DATE_EPOCH=1 +ENV CXXFLAGS="-include cstdint" +# ENV ROCKSDB_USE_PKG_CONFIG=0 + +# --mount=type=bind instead? +# --mount=type=bind,source=src,target=/app/src \ +COPY . . + +RUN --mount=type=bind,source=Cargo.toml,target=Cargo.toml,ro \ + --mount=type=bind,source=Cargo.lock,target=Cargo.lock,ro \ + --mount=type=cache,target=${HOME}/target/ \ + --mount=type=cache,target=/usr/local/cargo/registry/ \ + --mount=type=cache,target=${CARGO_TARGET_DIR} \ + --mount=type=cache,target=${CARGO_HOME} \ + cargo fetch --locked --target $TARGET_ARCH && \ + cargo metadata --locked --format-version=1 > /dev/null 2>&1 + +RUN --network=none \ + --mount=type=bind,source=Cargo.toml,target=Cargo.toml,ro \ + --mount=type=bind,source=Cargo.lock,target=Cargo.lock,ro \ + --mount=type=cache,target=${HOME}/target/ \ + --mount=type=cache,target=/usr/local/cargo/registry/ \ + --mount=type=cache,target=${CARGO_TARGET_DIR} \ + --mount=type=cache,target=${CARGO_HOME} \ + cargo build --frozen --release --features "${FEATURES}" --target ${TARGET_ARCH} && \ + install -D -m 0755 ${HOME}/target/${TARGET_ARCH}/release/zcash-devtool /usr/local/bin/zcash-devtool + +# This stage is used for exporting the binaries +FROM scratch AS export +COPY --from=release /usr/local/bin/* / + +# This stage starts from scratch using StageX and copies the built +# zcash-devtool binary from the `release` stage +FROM scratch AS runtime +COPY --from=setup /usr/bin/busybox . / +RUN ["busybox", "--install", "-s", "usr/bin"] + +ARG FEATURES +ENV FEATURES=${FEATURES} + +# Create a non-privileged user for running `zcash-devtool`. +# +# We use a high UID/GID (10801) to avoid overlap with host system users. +# This reduces the risk of container user namespace conflicts with host accounts, +# which could potentially lead to privilege escalation if a container escape occurs. +# +# We do not use the `--system` flag for user creation since: +# 1. System user ranges (100-999) can collide with host system users +# (see: https://github.com/nginxinc/docker-nginx/issues/490) +# 2. There's no value added and warning messages can be raised at build time +# (see: https://github.com/dotnet/dotnet-docker/issues/4624) +# +# The high UID/GID values provide an additional security boundary in containers +# where user namespaces are shared with the host. +ARG UID +ENV UID=${UID} +ARG GID +ENV GID=${GID} +ARG USER +ENV USER=${USER} +ARG HOME +ENV HOME=${HOME} + + +COPY --chmod=644 <<-EOF /etc/passwd + root:x:0:0:root:/root:/bin/sh + user:x:${UID}:${GID}::${HOME}:/bin/sh +EOF + +COPY --chmod=644 <<-EOF /etc/group + root:x:0: + user:x:${GID}: +EOF + +USER ${UID}:${GID} + +WORKDIR ${HOME} + +# We're explicitly NOT using the USER directive here. +# Instead, we run as root initially and use setpriv in the entrypoint.sh +# to step down to the non-privileged user. This allows us to change permissions +# on mounted volumes before running the application as a non-root user. +# User with UID=${UID} is created above and used via setpriv in entrypoint.sh. + +COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ +# COPY --chown=${UID}:${GID} ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh + +ENTRYPOINT [ "entrypoint.sh" ] +CMD ["zcash-devtool"] From afbf59851b9ffb575e41c2f77b64633169c4e206 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 00:47:21 -0500 Subject: [PATCH 03/26] update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8c6b6ef..1fe81be 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ # Guard against accidental commits of the `local` and `tmp` paths /local /tmp + +#StageX build directory +/build From a3d9c327996e2f37122fc6872d28a2ecd91c1edd Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 00:56:21 -0500 Subject: [PATCH 04/26] rm comments --- Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index b6cdbe7..628a2d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,10 +56,7 @@ ENV RUSTFLAGS="${RUSTFLAGS} -C link-arg=-Wl,--build-id=none" ENV SOURCE_DATE_EPOCH=1 ENV CXXFLAGS="-include cstdint" -# ENV ROCKSDB_USE_PKG_CONFIG=0 -# --mount=type=bind instead? -# --mount=type=bind,source=src,target=/app/src \ COPY . . RUN --mount=type=bind,source=Cargo.toml,target=Cargo.toml,ro \ From e4e9a32842f5c8da628f32155bc09feeffd16f77 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 01:17:34 -0500 Subject: [PATCH 05/26] update comments --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 628a2d2..f4ee36e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # stages: # - setup: sets default values -# - release: builds release binaries +# - release: builds release binary # - runtime: prepares the release image # # We first set default values for build arguments used across the stages. @@ -78,7 +78,7 @@ RUN --network=none \ cargo build --frozen --release --features "${FEATURES}" --target ${TARGET_ARCH} && \ install -D -m 0755 ${HOME}/target/${TARGET_ARCH}/release/zcash-devtool /usr/local/bin/zcash-devtool -# This stage is used for exporting the binaries +# This stage is used to export the binary FROM scratch AS export COPY --from=release /usr/local/bin/* / From 3663e99027a297d88cad4292b63a45e6a06dd344 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 18:57:40 -0500 Subject: [PATCH 06/26] cleanup --- compat.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compat.sh b/compat.sh index 43d6ecb..f2ad69d 100755 --- a/compat.sh +++ b/compat.sh @@ -8,6 +8,7 @@ die() { echo "$@" >&2 exit 1 } + ### Bail and instruct user on missing package to install for their platform die_pkg() { local -r package=${1?} @@ -35,6 +36,7 @@ die_pkg() { [ -n "$install_cmd" ] && echo "Try: \`${install_cmd}\`" >&2 exit 1 } + ### Check if actual binary version is >= minimum version check_version(){ local pkg="${1?}" @@ -53,6 +55,7 @@ check_version(){ ((10#${ver1[i]} < 10#${ver2[i]})) && die_pkg "${pkg}" "${need}" done } + ### Check if required binaries are installed at appropriate versions check_tools(){ if [ -z "${BASH_VERSINFO[0]}" ] \ @@ -74,9 +77,8 @@ check_tools(){ esac done } + check_tools docker buildx; docker info -f '{{ .DriverStatus }}' \ | grep "io.containerd.snapshotter.v1" >/dev/null \ || die "Error: Docker Engine is not using containerd for image storage" - - From c41119c20ee1ccda194e0cd31cc695bba2e246f7 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 18:58:06 -0500 Subject: [PATCH 07/26] add Makefile --- Makefile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5153de2 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +# Simple wrapper for scripts with printed status messages. +# +# Running `make` or `make stagex` will leverage the steps below +# to check compatibility and build the binary via StageX. + +.PHONY: stagex compat build + +stagex: compat build + @echo "stagex build completed via make! Thank you have a nice day." + +compat: + @echo "Beginning Compatibility Check step." + @./compat.sh + @echo " [PASS] Compatibility Check passed." + +build: + @echo "Entering Build step." + @./build.sh + @echo "Build step complete." From 67e8ff56e9c0a8b99f586d140cc88de4d5327759 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 19:23:28 -0500 Subject: [PATCH 08/26] update README --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6a6bdab..4a1581a 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,13 @@ scale experimentation, at your own risk. ## Usage -No binary artifacts are provided for this crate; it is generally used via -`cargo run` as follows: +No binary artifacts are directly provided for this crate. + +However, a bootstrapped and reproducable build pipeline using StageX is included. +To create a binary, you can simply run `make` in the root directory of the repo. +The resulting binary will be found in the `/build/` directory. + +It can also be used via `cargo run` as follows: To obtain the help docs: ``` From 0f50206a8b9785ce309e1d048e21c7b5266997f7 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 12 Feb 2026 20:32:08 -0500 Subject: [PATCH 09/26] cleanup --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5153de2..9e5041b 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ .PHONY: stagex compat build stagex: compat build - @echo "stagex build completed via make! Thank you have a nice day." + @echo "stagex build completed via make." compat: @echo "Beginning Compatibility Check step." From 97e19fda4ed06c4196f9167653c1563a23dc6b45 Mon Sep 17 00:00:00 2001 From: al amoda Date: Sun, 15 Feb 2026 03:15:47 -0500 Subject: [PATCH 10/26] fix spelling in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a1581a..49f0627 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ scale experimentation, at your own risk. No binary artifacts are directly provided for this crate. -However, a bootstrapped and reproducable build pipeline using StageX is included. +However, a bootstrapped and reproducible build pipeline using StageX is included. To create a binary, you can simply run `make` in the root directory of the repo. The resulting binary will be found in the `/build/` directory. From 1aa0623219213d6446bb1330fcc7cdac7ca28f39 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 07:51:53 -0500 Subject: [PATCH 11/26] build with --all-features, restrict runtime permissions --- Dockerfile | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index f4ee36e..6d88092 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,9 +36,6 @@ ENV CARGO_INCREMENTAL=${CARGO_INCREMENTAL:-0} ARG CARGO_HOME ENV CARGO_HOME=${CARGO_HOME} -ARG FEATURES -ENV FEATURES=${FEATURES} - # This stage builds the zcash-devtool release binary. FROM setup AS release @@ -75,7 +72,7 @@ RUN --network=none \ --mount=type=cache,target=/usr/local/cargo/registry/ \ --mount=type=cache,target=${CARGO_TARGET_DIR} \ --mount=type=cache,target=${CARGO_HOME} \ - cargo build --frozen --release --features "${FEATURES}" --target ${TARGET_ARCH} && \ + cargo build --frozen --release --all-features --target ${TARGET_ARCH} && \ install -D -m 0755 ${HOME}/target/${TARGET_ARCH}/release/zcash-devtool /usr/local/bin/zcash-devtool # This stage is used to export the binary @@ -114,13 +111,12 @@ ENV USER=${USER} ARG HOME ENV HOME=${HOME} - -COPY --chmod=644 <<-EOF /etc/passwd +COPY --chmod=550 <<-EOF /etc/passwd root:x:0:0:root:/root:/bin/sh user:x:${UID}:${GID}::${HOME}:/bin/sh EOF -COPY --chmod=644 <<-EOF /etc/group +COPY --chmod=550 <<-EOF /etc/group root:x:0: user:x:${GID}: EOF @@ -139,4 +135,4 @@ COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ # COPY --chown=${UID}:${GID} ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh ENTRYPOINT [ "entrypoint.sh" ] -CMD ["zcash-devtool"] +CMD [ "zcash-devtool" ] From 1ee0a9171f6d46012b1d7c106e6e9c7e48d2567c Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:13:40 -0500 Subject: [PATCH 12/26] add entrypoint.sh --- entrypoint.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 entrypoint.sh diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..70867e9 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# Entrypoint for running zcash-devtool in Docker. +# +# The main script logic is at the bottom. +# +# ## Notes +# +# zcash-devtool is a stateless tool. Each command has some effect: +# inspect +# Intended to be run against "anything zcash" and provide information. For example, +# an address, or a transaction. +# wallet +# Can create and inspect wallets, sync, send zec and so on. + +set -eo pipefail + +# Main Script Logic +# +# 1. Print environment variables and config for debugging. +# 2. Tests if zcash-devtool runs, printing help. +# 3. Execs the CMD or custom command provided. + +echo "INFO: Using the following environment variables:" +printenv + +echo "Testing zingo-cli to print version string:" +./zcash-devtool help + +echo "now exec'ing $@ " +exec "$@" From 7bd337818f8704ba9bf10c79749a4e0df5b47da7 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:14:15 -0500 Subject: [PATCH 13/26] add load_image.sh, update Makefile --- Makefile | 7 ++++++- load_image.sh | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 load_image.sh diff --git a/Makefile b/Makefile index 9e5041b..9aa5aca 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Running `make` or `make stagex` will leverage the steps below # to check compatibility and build the binary via StageX. -.PHONY: stagex compat build +.PHONY: stagex compat build load stagex: compat build @echo "stagex build completed via make." @@ -17,3 +17,8 @@ build: @echo "Entering Build step." @./build.sh @echo "Build step complete." + +load: + @echo "Attempting to load OCI image into local docker image store." + @./utils/load_image.sh + @echo "make load step complete." diff --git a/load_image.sh b/load_image.sh new file mode 100644 index 0000000..3031fa4 --- /dev/null +++ b/load_image.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +REPO_ROOT="$(git rev-parse --show-toplevel)" +OCI_OUTPUT="$REPO_ROOT/build/oci" + +# Build runtime image for docker run +echo "Checking if the OCI output from build is present." +if [ -f $OCI_OUTPUT/zcash-devtool.tar ]; +then + echo "OCI output file not present." +else + echo "OCI output file present, loading tar file into local docker image store." + docker load < $OCI_OUTPUT/zcash-devtool.tar + echo "...Done!" +fi + From 9c48faea949dc352c60073661f001f947d4f78cd Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:17:44 -0500 Subject: [PATCH 14/26] add utils dir for scripts --- build.sh => utils/build.sh | 0 compat.sh => utils/compat.sh | 0 entrypoint.sh => utils/entrypoint.sh | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename build.sh => utils/build.sh (100%) rename compat.sh => utils/compat.sh (100%) rename entrypoint.sh => utils/entrypoint.sh (100%) diff --git a/build.sh b/utils/build.sh similarity index 100% rename from build.sh rename to utils/build.sh diff --git a/compat.sh b/utils/compat.sh similarity index 100% rename from compat.sh rename to utils/compat.sh diff --git a/entrypoint.sh b/utils/entrypoint.sh similarity index 100% rename from entrypoint.sh rename to utils/entrypoint.sh From 454627b7b5309cb645aeacc2de1c29a092877e50 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:18:29 -0500 Subject: [PATCH 15/26] change runtime stage to busybox base image --- Dockerfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6d88092..5755ce8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,9 +81,7 @@ COPY --from=release /usr/local/bin/* / # This stage starts from scratch using StageX and copies the built # zcash-devtool binary from the `release` stage -FROM scratch AS runtime -COPY --from=setup /usr/bin/busybox . / -RUN ["busybox", "--install", "-s", "usr/bin"] +FROM busybox AS runtime ARG FEATURES ENV FEATURES=${FEATURES} @@ -132,7 +130,7 @@ WORKDIR ${HOME} # User with UID=${UID} is created above and used via setpriv in entrypoint.sh. COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ -# COPY --chown=${UID}:${GID} ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh +COPY --chown=${UID}:${GID} ./entrypoint.sh /usr/local/bin/entrypoint.sh ENTRYPOINT [ "entrypoint.sh" ] CMD [ "zcash-devtool" ] From c563d24bf7633c6cab9cf88ff513b05606774f81 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:19:14 -0500 Subject: [PATCH 16/26] update Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9aa5aca..44fca59 100644 --- a/Makefile +++ b/Makefile @@ -10,12 +10,12 @@ stagex: compat build compat: @echo "Beginning Compatibility Check step." - @./compat.sh + @./utils/compat.sh @echo " [PASS] Compatibility Check passed." build: @echo "Entering Build step." - @./build.sh + @./utils/build.sh @echo "Build step complete." load: From 73736a48a181d4ff021d16429c24a3d6fbc55c0f Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:24:16 -0500 Subject: [PATCH 17/26] adjust Dockerfile, mv load_image.sh --- Dockerfile | 2 +- load_image.sh => utils/load_image.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename load_image.sh => utils/load_image.sh (100%) diff --git a/Dockerfile b/Dockerfile index 5755ce8..5fd4101 100644 --- a/Dockerfile +++ b/Dockerfile @@ -130,7 +130,7 @@ WORKDIR ${HOME} # User with UID=${UID} is created above and used via setpriv in entrypoint.sh. COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ -COPY --chown=${UID}:${GID} ./entrypoint.sh /usr/local/bin/entrypoint.sh +COPY --chown=${UID}:${GID} ./utils/entrypoint.sh /usr/local/bin/entrypoint.sh ENTRYPOINT [ "entrypoint.sh" ] CMD [ "zcash-devtool" ] diff --git a/load_image.sh b/utils/load_image.sh similarity index 100% rename from load_image.sh rename to utils/load_image.sh From 3ce864e3514c57d8f13f2c0e401cbd10f1d64fbf Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:25:42 -0500 Subject: [PATCH 18/26] modify permissions --- utils/load_image.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 utils/load_image.sh diff --git a/utils/load_image.sh b/utils/load_image.sh old mode 100644 new mode 100755 From 643f2713406dfebb367129d1c345f23998b27788 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 08:52:42 -0500 Subject: [PATCH 19/26] add to load_image.sh --- utils/load_image.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/utils/load_image.sh b/utils/load_image.sh index 3031fa4..c14b5bc 100755 --- a/utils/load_image.sh +++ b/utils/load_image.sh @@ -4,15 +4,17 @@ set -e REPO_ROOT="$(git rev-parse --show-toplevel)" OCI_OUTPUT="$REPO_ROOT/build/oci" +TARBALL="${OCI_OUTPUT}/zcash-devtool.tar" + # Build runtime image for docker run echo "Checking if the OCI output from build is present." -if [ -f $OCI_OUTPUT/zcash-devtool.tar ]; +if [ -f "$TARBALL" ]; then - echo "OCI output file not present." -else echo "OCI output file present, loading tar file into local docker image store." - docker load < $OCI_OUTPUT/zcash-devtool.tar + docker load < $TARBALL echo "...Done!" +else + echo "OCI output file not present." fi From 459f7db739ad8779278a4ff093c8781e3be0172d Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 26 Feb 2026 09:30:34 -0500 Subject: [PATCH 20/26] set WORKDIR, add create wallet to Makefile, functioning stub create_wallet --- Dockerfile | 4 ++-- Makefile | 5 +++++ utils/create_wallet.sh | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100755 utils/create_wallet.sh diff --git a/Dockerfile b/Dockerfile index 5fd4101..1189844 100644 --- a/Dockerfile +++ b/Dockerfile @@ -121,7 +121,7 @@ EOF USER ${UID}:${GID} -WORKDIR ${HOME} +WORKDIR /usr/local/bin # We're explicitly NOT using the USER directive here. # Instead, we run as root initially and use setpriv in the entrypoint.sh @@ -133,4 +133,4 @@ COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ COPY --chown=${UID}:${GID} ./utils/entrypoint.sh /usr/local/bin/entrypoint.sh ENTRYPOINT [ "entrypoint.sh" ] -CMD [ "zcash-devtool" ] +CMD [ "./zcash-devtool" ] diff --git a/Makefile b/Makefile index 44fca59..d061180 100644 --- a/Makefile +++ b/Makefile @@ -22,3 +22,8 @@ load: @echo "Attempting to load OCI image into local docker image store." @./utils/load_image.sh @echo "make load step complete." + +create: + @echo "Attempting to make zcash-devtool wallet, if there is none. The docker container's runtime shares the host kernel's entropy source." + @./utils/create_wallet.sh + @echo "Wallet creation script complete." diff --git a/utils/create_wallet.sh b/utils/create_wallet.sh new file mode 100755 index 0000000..9e69d3a --- /dev/null +++ b/utils/create_wallet.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +echo "Checking local docker image store to see if a zcash-devtool:latest image is present." +# Checks for empty string, discarding error messages. +if [ -z "$(docker images -q zcash-devtool:latest 2>/dev/null)" ]; then + echo "There is no zcash-devtool:latest image listed by docker." +else + echo "Creating wallet if there is none, then printing wallet's orchard u address." + docker run zcash-devtool:latest ./zcash-devtool wallet help +fi From 651f636c89802c1ffcbf34806f0da7ac3f6f2003 Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 27 Feb 2026 06:50:46 -0500 Subject: [PATCH 21/26] update create_wallet.sh --- Makefile | 4 ++-- utils/create_wallet.sh | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index d061180..836d15e 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Running `make` or `make stagex` will leverage the steps below # to check compatibility and build the binary via StageX. -.PHONY: stagex compat build load +.PHONY: stagex compat build load create stagex: compat build @echo "stagex build completed via make." @@ -24,6 +24,6 @@ load: @echo "make load step complete." create: - @echo "Attempting to make zcash-devtool wallet, if there is none. The docker container's runtime shares the host kernel's entropy source." + @echo "Making zcash-devtool wallet. This requires user input. The docker container's runtime shares the host kernel's entropy source." @./utils/create_wallet.sh @echo "Wallet creation script complete." diff --git a/utils/create_wallet.sh b/utils/create_wallet.sh index 9e69d3a..b3677c9 100755 --- a/utils/create_wallet.sh +++ b/utils/create_wallet.sh @@ -7,6 +7,7 @@ echo "Checking local docker image store to see if a zcash-devtool:latest image i if [ -z "$(docker images -q zcash-devtool:latest 2>/dev/null)" ]; then echo "There is no zcash-devtool:latest image listed by docker." else - echo "Creating wallet if there is none, then printing wallet's orchard u address." - docker run zcash-devtool:latest ./zcash-devtool wallet help + + echo "Creating wallet, which requires user input. Connecting via clearnet to zecrocks." + docker run -it zcash-devtool:latest ./zcash-devtool wallet init --name "stagex_container_wallet" --identity ./age_id.txt --connection direct --network test -s zecrocks fi From ec1872fe4111fc3470f9733917affca45db76198 Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 27 Feb 2026 07:30:19 -0500 Subject: [PATCH 22/26] mkdir and set container permissions with root, run with user, cleanup --- Dockerfile | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1189844..91a05ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ ARG FEATURES="" ARG UID=10801 ARG GID=${UID} -ARG USER="devtool-user" +ARG USER="user" ARG HOME="/home/${USER}" ARG CARGO_HOME="${HOME}/.cargo" ARG CARGO_TARGET_DIR="${HOME}/target" @@ -123,14 +123,11 @@ USER ${UID}:${GID} WORKDIR /usr/local/bin -# We're explicitly NOT using the USER directive here. -# Instead, we run as root initially and use setpriv in the entrypoint.sh -# to step down to the non-privileged user. This allows us to change permissions -# on mounted volumes before running the application as a non-root user. -# User with UID=${UID} is created above and used via setpriv in entrypoint.sh. - -COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ +USER root +COPY --from=release --chown=${UID}:${GID} /usr/local/bin/zcash-devtool /usr/local/bin/ COPY --chown=${UID}:${GID} ./utils/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN mkdir -p /usr/local/bin/zec_sqlite_wallet && chown -R ${UID}:${GID} /usr/local/bin/ && chmod -R 770 /usr/local/bin/ && chmod 550 /usr/local/bin/zcash-devtool +USER $USER ENTRYPOINT [ "entrypoint.sh" ] CMD [ "./zcash-devtool" ] From a6ed9a305c97c29ebcb96212d7ab6384ef03ca75 Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 27 Feb 2026 07:33:59 -0500 Subject: [PATCH 23/26] cleanup --- utils/create_wallet.sh | 3 +-- utils/entrypoint.sh | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/create_wallet.sh b/utils/create_wallet.sh index b3677c9..56f5687 100755 --- a/utils/create_wallet.sh +++ b/utils/create_wallet.sh @@ -7,7 +7,6 @@ echo "Checking local docker image store to see if a zcash-devtool:latest image i if [ -z "$(docker images -q zcash-devtool:latest 2>/dev/null)" ]; then echo "There is no zcash-devtool:latest image listed by docker." else - - echo "Creating wallet, which requires user input. Connecting via clearnet to zecrocks." + echo "Creating wallet. Connecting via clearnet to zecrocks." docker run -it zcash-devtool:latest ./zcash-devtool wallet init --name "stagex_container_wallet" --identity ./age_id.txt --connection direct --network test -s zecrocks fi diff --git a/utils/entrypoint.sh b/utils/entrypoint.sh index 70867e9..43533b3 100755 --- a/utils/entrypoint.sh +++ b/utils/entrypoint.sh @@ -24,7 +24,7 @@ set -eo pipefail echo "INFO: Using the following environment variables:" printenv -echo "Testing zingo-cli to print version string:" +echo "Testing zcash-devtool to print version string:" ./zcash-devtool help echo "now exec'ing $@ " From 88db0e52c52402db1e432eda04fee2e841d4d678 Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 27 Feb 2026 07:35:56 -0500 Subject: [PATCH 24/26] streamline --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 91a05ca..3a80bcb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -124,8 +124,8 @@ USER ${UID}:${GID} WORKDIR /usr/local/bin USER root -COPY --from=release --chown=${UID}:${GID} /usr/local/bin/zcash-devtool /usr/local/bin/ -COPY --chown=${UID}:${GID} ./utils/entrypoint.sh /usr/local/bin/entrypoint.sh +COPY --from=release /usr/local/bin/zcash-devtool /usr/local/bin/ +COPY ./utils/entrypoint.sh /usr/local/bin/entrypoint.sh RUN mkdir -p /usr/local/bin/zec_sqlite_wallet && chown -R ${UID}:${GID} /usr/local/bin/ && chmod -R 770 /usr/local/bin/ && chmod 550 /usr/local/bin/zcash-devtool USER $USER From 8b48e7fdeac8d84f6addc55cec3ea72b1562f500 Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 27 Feb 2026 07:37:33 -0500 Subject: [PATCH 25/26] cleanup --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3a80bcb..f820e23 100644 --- a/Dockerfile +++ b/Dockerfile @@ -79,7 +79,7 @@ RUN --network=none \ FROM scratch AS export COPY --from=release /usr/local/bin/* / -# This stage starts from scratch using StageX and copies the built +# This stage starts from StageX/busybox and copies the built # zcash-devtool binary from the `release` stage FROM busybox AS runtime From 5f3027ce5ff2b523822a41cd57ef5f31f54fcd7a Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 27 Feb 2026 07:41:32 -0500 Subject: [PATCH 26/26] add comment --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index f820e23..c725f2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ # stages: # - setup: sets default values # - release: builds release binary +# - export: minimal binary export # - runtime: prepares the release image # # We first set default values for build arguments used across the stages.