diff --git a/resources/charts/bitcoincore/templates/_helpers.tpl b/resources/charts/bitcoincore/templates/_helpers.tpl index 1adc5d205..dc3bf9ce6 100644 --- a/resources/charts/bitcoincore/templates/_helpers.tpl +++ b/resources/charts/bitcoincore/templates/_helpers.tpl @@ -61,8 +61,7 @@ Create the name of the service account to use Add network section heading in bitcoin.conf after v0.17.0 */}} {{- define "bitcoincore.check_semver" -}} -{{- $tag := .Values.image.tag | trimPrefix "v" -}} -{{- $version := semverCompare ">=0.17.0" $tag -}} +{{- $version := semverCompare ">=0.17.0" .Values.image.tag -}} {{- if $version -}} [{{ .Values.chain }}] {{- end -}} diff --git a/resources/charts/bitcoincore/values.yaml b/resources/charts/bitcoincore/values.yaml index 2498fee6d..2c9962b8a 100644 --- a/resources/charts/bitcoincore/values.yaml +++ b/resources/charts/bitcoincore/values.yaml @@ -117,7 +117,6 @@ prometheusMetricsPort: 9332 baseConfig: | checkmempool=0 - acceptnonstdtxn=1 debuglogfile=0 logips=1 logtimemicros=1 diff --git a/resources/images/bitcoin/insecure/Dockerfile b/resources/images/bitcoin/insecure/Dockerfile new file mode 100644 index 000000000..e8bcb986c --- /dev/null +++ b/resources/images/bitcoin/insecure/Dockerfile @@ -0,0 +1,168 @@ +# Base stage +# ---------- +# +# We use the alpine version to get the +# correct version of glibc / gcc for building older bitcoin +# core versions. + +# Default is set here to quiet a warning from Docker, but the caller must +# be sure to ALWAYS set this correct per the version of bitcoin core they are +# trying to build +ARG ALPINE_VERSION=3.7 +FROM alpine:${ALPINE_VERSION} AS base + +# Setup deps stage +# ---------------- +# +# this installs the common dependencies for all of the old versions +# and then version specific dependencies are passed via the +# EXTRA_PACKAGES ARG +FROM base AS deps +ARG EXTRA_PACKAGES="" +RUN --mount=type=cache,target=/var/cache/apk \ + sed -i 's/http\:\/\/dl-cdn.alpinelinux.org/https\:\/\/alpine.global.ssl.fastly.net/g' /etc/apk/repositories \ + && apk --no-cache add \ + autoconf \ + automake \ + boost-dev \ + build-base \ + ccache \ + chrpath \ + file \ + gnupg \ + git \ + libevent-dev \ + libressl \ + libtool \ + linux-headers \ + zeromq-dev \ + ${EXTRA_PACKAGES} + +ENV BERKELEYDB_VERSION=db-4.8.30.NC +ENV BERKELEYDB_PREFIX=/opt/${BERKELEYDB_VERSION} + +RUN wget https://download.oracle.com/berkeley-db/${BERKELEYDB_VERSION}.tar.gz +RUN tar -xzf *.tar.gz +RUN sed s/__atomic_compare_exchange/__atomic_compare_exchange_db/g -i ${BERKELEYDB_VERSION}/dbinc/atomic.h +RUN mkdir -p ${BERKELEYDB_PREFIX} + +WORKDIR /${BERKELEYDB_VERSION}/build_unix + +RUN ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=${BERKELEYDB_PREFIX} +RUN make -j$(nproc) +RUN make install +RUN rm -rf ${BERKELEYDB_PREFIX}/docs + +# Build stage +# ----------- +# +# We can build from a git repo using the REPO and COMMIT_SHA args +# or from a local directory using FROM_SRC=true and specifying the local +# source directory. Build args are set using a default but can be changed +# on an imnage by image basis, if needed +# +# PRE_CONFIGURE_COMMANDS is used for version specific fixes needed before +# running ./autogen.sh && ./configure +# +# EXTRA_BUILD_ARGS is used for version specific build flags +FROM deps AS build +ARG FROM_SRC="false" +ARG REPO="" +ARG COMMIT_SHA="" +ARG BUILD_ARGS="--disable-tests --without-gui --disable-bench --disable-fuzz-binary --enable-suppress-external-warnings" +ARG EXTRA_BUILD_ARGS="" +ARG PRE_CONFIGURE_COMMANDS="" + +COPY --from=deps /opt /opt +ENV BITCOIN_PREFIX=/opt/bitcoin +WORKDIR /build + +# Even if not being used, --build-context bitcoin-src must be specified else +# this line will error. If building from a remote repo, use something like +# --build-context bitcoin-src="." +COPY --from=bitcoin-src . /tmp/bitcoin-source +RUN if [ "$FROM_SRC" = "true" ]; then \ + # run with --progress=plain to see these log outputs + echo "Using local files from /tmp/bitcoin-source"; \ + if [ -d "/tmp/bitcoin-source" ] && [ "$(ls -A /tmp/bitcoin-source)" ]; then \ + cp -R /tmp/bitcoin-source /build/bitcoin; \ + else \ + echo "Error: Local source directory is empty or does not exist" && exit 1; \ + fi \ + else \ + echo "Cloning from git repository"; \ + git clone --depth 1 "https://github.com/${REPO}" /build/bitcoin \ + && cd /build/bitcoin \ + && git fetch --depth 1 origin "$COMMIT_SHA" \ + && git checkout "$COMMIT_SHA"; \ + fi; + +# This is not our local ccache, but ccache in the docker cache +# this does speed up builds substantially when building from source or building +# multiple versions sequentially +ENV CCACHE_DIR=/ccache +RUN --mount=type=cache,target=/ccache \ + set -ex \ + && cd /build/bitcoin \ + && if [ -n "$PRE_CONFIGURE_COMMANDS" ]; then \ + eval ${PRE_CONFIGURE_COMMANDS}; \ + fi \ + && ./autogen.sh \ + && ./configure \ + LDFLAGS=-L`ls -d /opt/db*`/lib/ \ + CPPFLAGS="-g0 -I`ls -d /opt/db*`/include/ --param ggc-min-expand=1 --param ggc-min-heapsize=32768" \ + --prefix=${BITCOIN_PREFIX} \ + ${BUILD_ARGS} \ + ${EXTRA_BUILD_ARGS} \ + --with-daemon \ + && make -j$(nproc) \ + && make install \ + && strip ${BITCOIN_PREFIX}/bin/bitcoin-cli \ + && strip ${BITCOIN_PREFIX}/bin/bitcoind \ + && rm -f ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.a \ + && rm -f ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.so.0.0.0 \ + && rm -f ${BITCOIN_PREFIX}/bin/bitcoin-tx \ + && rm -f ${BITCOIN_PREFIX}/bin/bitcoin-wallet + +# verify ccache is working, specify --progress=plain to see output in build logs +RUN ccache -s + +# Final clean stage +# ----------------- +# +# EXTRA_RUNTIME_PACKAGES is used for version specific runtime deps +FROM alpine:${ALPINE_VERSION} +ARG EXTRA_RUNTIME_PACKAGES="" +ARG UID=100 +ARG GID=101 +ARG BITCOIN_VERSION +ENV BITCOIN_DATA=/root/.bitcoin +ENV BITCOIN_PREFIX=/opt/bitcoin +ENV PATH=${BITCOIN_PREFIX}/bin:$PATH +ENV BITCOIN_VERSION=${BITCOIN_VERSION} +LABEL maintainer.0="bitcoindevproject" + +RUN addgroup -g ${GID} -S bitcoin +RUN adduser -u ${UID} -S bitcoin -G bitcoin +RUN --mount=type=cache,target=/var/cache/apk sed -i 's/http\:\/\/dl-cdn.alpinelinux.org/https\:\/\/alpine.global.ssl.fastly.net/g' /etc/apk/repositories \ + && apk --no-cache add \ + bash \ + boost-filesystem \ + boost-system \ + boost-thread \ + libevent \ + libzmq \ + shadow \ + sqlite-dev \ + su-exec \ + ${EXTRA_RUNTIME_PACKAGES} + +COPY --from=build /opt/bitcoin /usr/local +COPY entrypoint.sh /entrypoint.sh + +VOLUME ["/home/bitcoin/.bitcoin"] +EXPOSE 8332 8333 18332 18333 18443 18444 38333 38332 + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["bitcoind"] + diff --git a/resources/images/bitcoin/insecure/addrman_v0.16.1.patch b/resources/images/bitcoin/insecure/addrman_v0.16.1.patch new file mode 100644 index 000000000..bc8a73bf8 --- /dev/null +++ b/resources/images/bitcoin/insecure/addrman_v0.16.1.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 4fbfa2b5c85..0d8d5751268 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -455,6 +455,8 @@ std::vector CNetAddr::GetGroup() const + vchRet.push_back(NET_IPV4); + vchRet.push_back(GetByte(3) ^ 0xFF); + vchRet.push_back(GetByte(2) ^ 0xFF); ++ vchRet.push_back(GetByte(1) ^ 0xFF); ++ vchRet.push_back(GetByte(0) ^ 0xFF); + return vchRet; + } + else if (IsTor()) diff --git a/resources/images/bitcoin/insecure/addrman_v0.17.0.patch b/resources/images/bitcoin/insecure/addrman_v0.17.0.patch new file mode 100644 index 000000000..265a30b6e --- /dev/null +++ b/resources/images/bitcoin/insecure/addrman_v0.17.0.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 778c2700f95..03d97bcd673 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -354,6 +354,8 @@ std::vector CNetAddr::GetGroup() const + vchRet.push_back(NET_IPV4); + vchRet.push_back(GetByte(3) ^ 0xFF); + vchRet.push_back(GetByte(2) ^ 0xFF); ++ vchRet.push_back(GetByte(1) ^ 0xFF); ++ vchRet.push_back(GetByte(0) ^ 0xFF); + return vchRet; + } + else if (IsTor()) diff --git a/resources/images/bitcoin/insecure/addrman_v0.19.2.patch b/resources/images/bitcoin/insecure/addrman_v0.19.2.patch new file mode 100644 index 000000000..bc8a73bf8 --- /dev/null +++ b/resources/images/bitcoin/insecure/addrman_v0.19.2.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 4fbfa2b5c85..0d8d5751268 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -455,6 +455,8 @@ std::vector CNetAddr::GetGroup() const + vchRet.push_back(NET_IPV4); + vchRet.push_back(GetByte(3) ^ 0xFF); + vchRet.push_back(GetByte(2) ^ 0xFF); ++ vchRet.push_back(GetByte(1) ^ 0xFF); ++ vchRet.push_back(GetByte(0) ^ 0xFF); + return vchRet; + } + else if (IsTor()) diff --git a/resources/images/bitcoin/insecure/addrman_v0.20.0.patch b/resources/images/bitcoin/insecure/addrman_v0.20.0.patch new file mode 100644 index 000000000..db638357c --- /dev/null +++ b/resources/images/bitcoin/insecure/addrman_v0.20.0.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 228caf74a93..a6728321d1d 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -517,6 +517,8 @@ std::vector CNetAddr::GetGroup(const std::vector &asmap) co + uint32_t ipv4 = GetLinkedIPv4(); + vchRet.push_back((ipv4 >> 24) & 0xFF); + vchRet.push_back((ipv4 >> 16) & 0xFF); ++ vchRet.push_back((ipv4 >> 8) & 0xFF); ++ vchRet.push_back(ipv4 & 0xFF); + return vchRet; + } else if (IsTor()) { + nStartByte = 6; diff --git a/resources/images/bitcoin/insecure/addrman_v0.21.1.patch b/resources/images/bitcoin/insecure/addrman_v0.21.1.patch new file mode 100644 index 000000000..c85679b16 --- /dev/null +++ b/resources/images/bitcoin/insecure/addrman_v0.21.1.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index e0d4638dd6a..a84b3980f30 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -742,6 +742,8 @@ std::vector CNetAddr::GetGroup(const std::vector &asmap) co + uint32_t ipv4 = GetLinkedIPv4(); + vchRet.push_back((ipv4 >> 24) & 0xFF); + vchRet.push_back((ipv4 >> 16) & 0xFF); ++ vchRet.push_back((ipv4 >> 8) & 0xFF); ++ vchRet.push_back(ipv4 & 0xFF); + return vchRet; + } else if (IsTor() || IsI2P() || IsCJDNS()) { + nBits = 4; diff --git a/resources/images/bitcoin/insecure/build.md b/resources/images/bitcoin/insecure/build.md new file mode 100644 index 000000000..68502d51b --- /dev/null +++ b/resources/images/bitcoin/insecure/build.md @@ -0,0 +1,89 @@ +# Historic CVE images + +These images are for old versions of Bitcoin Core with known CVEs. These images have signet backported +and the addrman and isroutable patches applied. + +# Build incantations + +Run from top-level of project + +## v0.21.1 + +```bash +docker buildx build \ + --platform linux/amd64,linux/armhf \ + --build-context bitcoin-src="." \ + --build-arg ALPINE_VERSION="3.17" \ + --build-arg BITCOIN_VERSION="0.21.1" \ + --build-arg EXTRA_PACKAGES="sqlite-dev" \ + --build-arg EXTRA_RUNTIME_PACKAGES="boost-filesystem sqlite-dev" \ + --build-arg REPO="josibake/bitcoin" \ + --build-arg COMMIT_SHA="e0a22f14c15b4877ef6221f9ee2dfe510092d734" \ + --tag bitcoindevproject/bitcoin:0.21.1 \ + resources/images/bitcoin/insecure +``` + +## v0.20.0 + +```bash +docker buildx build \ + --platform linux/amd64,linux/armhf \ + --build-context bitcoin-src="." \ + --build-arg ALPINE_VERSION="3.12.12" \ + --build-arg BITCOIN_VERSION="0.20.0" \ + --build-arg EXTRA_PACKAGES="sqlite-dev miniupnpc" \ + --build-arg EXTRA_RUNTIME_PACKAGES="boost-filesystem sqlite-dev" \ + --build-arg REPO="josibake/bitcoin" \ + --build-arg COMMIT_SHA="0bbff8feff0acf1693dfe41184d9a4fd52001d3f" \ + --tag bitcoindevproject/bitcoin:0.20.0 \ + resources/images/bitcoin/insecure +``` + +## v0.19.2 + +```bash +docker buildx build \ + --platform linux/amd64,linux/armhf \ + --build-context bitcoin-src="." \ + --build-arg ALPINE_VERSION="3.12.12" \ + --build-arg BITCOIN_VERSION="0.19.2" \ + --build-arg EXTRA_PACKAGES="sqlite-dev libressl-dev" \ + --build-arg EXTRA_RUNTIME_PACKAGES="boost-chrono boost-filesystem libressl sqlite-dev" \ + --build-arg REPO="josibake/bitcoin" \ + --build-arg COMMIT_SHA="e20f83eb5466a7d68227af14a9d0cf66fb520ffc" \ + --tag bitcoindevproject/bitcoin:0.19.2 \ + resources/images/bitcoin/insecure +``` + +## v0.17.0 + +```bash +docker buildx build \ + --platform linux/amd64,linux/armhf \ + --build-context bitcoin-src="." \ + --build-arg ALPINE_VERSION="3.9" \ + --build-arg BITCOIN_VERSION="0.17.0" \ + --build-arg EXTRA_PACKAGES="protobuf-dev libressl-dev" \ + --build-arg EXTRA_RUNTIME_PACKAGES="boost boost-program_options libressl sqlite-dev" \ + --build-arg REPO="josibake/bitcoin" \ + --build-arg COMMIT_SHA="f6b2db49a707e7ad433d958aee25ce561c66521a" \ + --tag bitcoindevproject/bitcoin:0.17.0 \ + resources/images/bitcoin/insecure +``` + +## v0.16.1 + +```bash +docker buildx build \ + --platform linux/amd64,linux/armhf \ + --build-context bitcoin-src="." \ + --build-arg ALPINE_VERSION="3.7" \ + --build-arg BITCOIN_VERSION="0.16.1" \ + --build-arg EXTRA_PACKAGES="protobuf-dev libressl-dev" \ + --build-arg PRE_CONFIGURE_COMMANDS="sed -i '/AC_PREREQ/a\AR_FLAGS=cr' src/univalue/configure.ac && sed -i '/AX_PROG_CC_FOR_BUILD/a\AR_FLAGS=cr' src/secp256k1/configure.ac && sed -i 's:sys/fcntl.h:fcntl.h:' src/compat.h" \ + --build-arg EXTRA_RUNTIME_PACKAGES="boost boost-program_options libressl" \ + --build-arg REPO="josibake/bitcoin" \ + --build-arg COMMIT_SHA="dc94c00e58c60412a4e1a540abdf0b56093179e8" \ + --tag bitcoindevproject/bitcoin:0.16.1 \ + resources/images/bitcoin/insecure +``` diff --git a/resources/images/bitcoin/insecure/entrypoint.sh b/resources/images/bitcoin/insecure/entrypoint.sh new file mode 100755 index 000000000..56d55b5d6 --- /dev/null +++ b/resources/images/bitcoin/insecure/entrypoint.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +if [ "$(echo "$1" | cut -c1)" = "-" ]; then + echo "$0: assuming arguments for bitcoind" + + set -- bitcoind "$@" +fi + +if [ "$(echo "$1" | cut -c1)" = "-" ] || [ "$1" = "bitcoind" ]; then + mkdir -p "$BITCOIN_DATA" + chmod 700 "$BITCOIN_DATA" + echo "$0: setting data directory to $BITCOIN_DATA" + set -- "$@" -datadir="$BITCOIN_DATA" +fi + +# Incorporate additional arguments for bitcoind if BITCOIN_ARGS is set. +if [ -n "$BITCOIN_ARGS" ]; then + IFS=' ' read -ra ARG_ARRAY <<< "$BITCOIN_ARGS" + set -- "$@" "${ARG_ARRAY[@]}" +fi + +# Conditionally add -printtoconsole for Bitcoin version 0.16.1 +if [ "${BITCOIN_VERSION}" == "0.16.1" ]; then + exec "$@" -printtoconsole +else + exec "$@" +fi diff --git a/resources/images/bitcoin/insecure/isroutable_v0.16.1.patch b/resources/images/bitcoin/insecure/isroutable_v0.16.1.patch new file mode 100644 index 000000000..0d9d4ad54 --- /dev/null +++ b/resources/images/bitcoin/insecure/isroutable_v0.16.1.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 81f72879f40..8aae93a6b68 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -231,7 +231,7 @@ bool CNetAddr::IsValid() const + + bool CNetAddr::IsRoutable() const + { +- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal()); ++ return true; + } + + bool CNetAddr::IsInternal() const diff --git a/resources/images/bitcoin/insecure/isroutable_v0.17.0.patch b/resources/images/bitcoin/insecure/isroutable_v0.17.0.patch new file mode 100644 index 000000000..f8d1fef08 --- /dev/null +++ b/resources/images/bitcoin/insecure/isroutable_v0.17.0.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 778c2700f95..9655b01efba 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -226,7 +226,7 @@ bool CNetAddr::IsValid() const + + bool CNetAddr::IsRoutable() const + { +- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal()); ++ return true; + } + + bool CNetAddr::IsInternal() const diff --git a/resources/images/bitcoin/insecure/isroutable_v0.19.2.patch b/resources/images/bitcoin/insecure/isroutable_v0.19.2.patch new file mode 100644 index 000000000..295569cd2 --- /dev/null +++ b/resources/images/bitcoin/insecure/isroutable_v0.19.2.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 228caf74a93..d1290d4de49 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -300,7 +300,7 @@ bool CNetAddr::IsValid() const + */ + bool CNetAddr::IsRoutable() const + { +- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal()); ++ return true; + } + + /** diff --git a/resources/images/bitcoin/insecure/isroutable_v0.20.0.patch b/resources/images/bitcoin/insecure/isroutable_v0.20.0.patch new file mode 100644 index 000000000..295569cd2 --- /dev/null +++ b/resources/images/bitcoin/insecure/isroutable_v0.20.0.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index 228caf74a93..d1290d4de49 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -300,7 +300,7 @@ bool CNetAddr::IsValid() const + */ + bool CNetAddr::IsRoutable() const + { +- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal()); ++ return true; + } + + /** diff --git a/resources/images/bitcoin/insecure/isroutable_v0.21.1.patch b/resources/images/bitcoin/insecure/isroutable_v0.21.1.patch new file mode 100644 index 000000000..ab8cbb7a5 --- /dev/null +++ b/resources/images/bitcoin/insecure/isroutable_v0.21.1.patch @@ -0,0 +1,13 @@ +diff --git a/src/netaddress.cpp b/src/netaddress.cpp +index e0d4638dd6a..2615e076b50 100644 +--- a/src/netaddress.cpp ++++ b/src/netaddress.cpp +@@ -465,7 +465,7 @@ bool CNetAddr::IsValid() const + */ + bool CNetAddr::IsRoutable() const + { +- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal()); ++ return true; + } + + /** diff --git a/src/warnet/image.py b/src/warnet/image.py index 6965838b6..c43323f15 100644 --- a/src/warnet/image.py +++ b/src/warnet/image.py @@ -7,22 +7,27 @@ @click.group(name="image") def image(): - """Build a a custom Warnet Bitcoin Core image""" + """Build a custom Warnet Bitcoin Core image""" @image.command() @click.option("--repo", required=True, type=str) @click.option("--commit-sha", required=True, type=str) @click.option("--registry", required=True, type=str) -@click.option("--tag", required=True, type=str) +@click.option( + "--tags", + required=True, + type=str, + help="Comma-separated list of full tags including image names", +) @click.option("--build-args", required=False, type=str) @click.option("--arches", required=False, type=str) @click.option("--action", required=False, type=str, default="load") -def build(repo, commit_sha, registry, tag, build_args, arches, action): +def build(repo, commit_sha, registry, tags, build_args, arches, action): """ - Build bitcoind and bitcoin-cli from at as :. + Build bitcoind and bitcoin-cli from at with the specified . Optionally deploy to remote registry using --action=push, otherwise image is loaded to local registry. """ - res = build_image(repo, commit_sha, registry, tag, build_args, arches, action) + res = build_image(repo, commit_sha, registry, tags, build_args, arches, action) if not res: sys.exit(1) diff --git a/src/warnet/image_build.py b/src/warnet/image_build.py index 98f502e23..67367afab 100644 --- a/src/warnet/image_build.py +++ b/src/warnet/image_build.py @@ -18,7 +18,7 @@ def build_image( repo: str, commit_sha: str, docker_registry: str, - tag: str, + tags: str, build_args: str, arches: str, action: str, @@ -42,7 +42,7 @@ def build_image( print(f"{repo=:}") print(f"{commit_sha=:}") print(f"{docker_registry=:}") - print(f"{tag=:}") + print(f"{tags=:}") print(f"{build_args=:}") print(f"{build_arches=:}") @@ -52,14 +52,13 @@ def build_image( use_builder_cmd = f"docker buildx use --builder {builder_name}" cleanup_builder_cmd = f"docker buildx rm {builder_name}" - if not run_command(create_builder_cmd): # noqa: SIM102 - # try to use existing - if not run_command(use_builder_cmd): - print(f"Could not create or use builder {builder_name} and create new builder") - return False + if not run_command(create_builder_cmd) and not run_command(use_builder_cmd): + print(f"Could not create or use builder {builder_name} and create new builder") + return False - image_full_name = f"{docker_registry}:{tag}" - print(f"{image_full_name=}") + tag_list = tags.split(",") + tag_args = " ".join([f"--tag {tag.strip()}" for tag in tag_list]) + print(f"{tag_args=}") platforms = ",".join([f"linux/{arch}" for arch in build_arches]) @@ -69,7 +68,7 @@ def build_image( f" --build-arg REPO={repo}" f" --build-arg COMMIT_SHA={commit_sha}" f" --build-arg BUILD_ARGS={build_args}" - f" --tag {image_full_name}" + f" {tag_args}" f" --file {dockerfile_path}" f" {dockerfile_path.parent}" f" --{action}" @@ -82,7 +81,6 @@ def build_image( except Exception as e: print(f"Error:\n{e}") finally: - # Tidy up the buildx builder if not run_command(cleanup_builder_cmd): print("Warning: Failed to remove the buildx builder.") else: diff --git a/src/warnet/network.py b/src/warnet/network.py index 92e5cda16..6c42e0b5d 100644 --- a/src/warnet/network.py +++ b/src/warnet/network.py @@ -63,6 +63,11 @@ def copy_scenario_defaults(directory: Path): ) +def is_connection_manual(peer): + # newer nodes specify a "connection_type" + return bool(peer.get("connection_type") == "manual" or peer.get("addnode") is True) + + def _connected(end="\n"): tanks = get_mission("tank") for tank in tanks: @@ -70,7 +75,7 @@ def _connected(end="\n"): peerinfo = json.loads(_rpc(tank.metadata.name, "getpeerinfo", "")) actual = 0 for peer in peerinfo: - if peer["connection_type"] == "manual": + if is_connection_manual(peer): actual += 1 expected = int(tank.metadata.annotations["init_peers"]) print(f"Tank {tank.metadata.name} peers expected: {expected}, actual: {actual}", end=end) diff --git a/test/data/bitcoin_conf/network.yaml b/test/data/bitcoin_conf/network.yaml index 0ceb8b059..f1d1a8124 100644 --- a/test/data/bitcoin_conf/network.yaml +++ b/test/data/bitcoin_conf/network.yaml @@ -1,35 +1,35 @@ nodes: - name: tank-0016 image: - tag: "v0.16.1" + tag: "0.16.1" connect: - tank-0017 config: uacomment=tank-0016 - name: tank-0017 image: - tag: "v0.17.0" + tag: "0.17.0" connect: - tank-0019 config: uacomment=tank-0017 - name: tank-0019 image: - tag: "v0.19.2" + tag: "0.19.2" connect: - tank-0020 config: uacomment=tank-0019 - name: tank-0020 image: - tag: "v0.20.0" + tag: "0.20.0" connect: - tank-0021 config: uacomment=tank-0020 - name: tank-0021 image: - tag: "v0.21.1" + tag: "0.21.1" connect: - tank-0024 config: diff --git a/test/data/signet/network.yaml b/test/data/signet/network.yaml index 5677909cf..eb422fddf 100644 --- a/test/data/signet/network.yaml +++ b/test/data/signet/network.yaml @@ -1,8 +1,52 @@ nodes: - name: miner - - name: tank-0001 + - name: tank-1 + image: + tag: "0.16.1" connect: - miner - - name: tank-0002 + - name: tank-2 + image: + tag: "0.17.0" connect: - - miner \ No newline at end of file + - miner + - name: tank-3 + image: + tag: "0.19.2" + connect: + - miner + - name: tank-4 + image: + tag: "0.20.0" + connect: + - miner + - name: tank-5 + image: + tag: "0.21.1" + connect: + - miner + - name: tank-6 + image: + tag: "24.2" + connect: + - miner + - name: tank-7 + image: + tag: "25.1" + connect: + - miner + - name: tank-8 + image: + tag: "26.0" + connect: + - miner + - name: tank-9 + image: + tag: "27.0" + connect: + - miner + - name: tank-10 + image: + tag: "0.16.1" + connect: + - miner diff --git a/test/data/signet/node-defaults.yaml b/test/data/signet/node-defaults.yaml index 4cf7b508b..43523c669 100644 --- a/test/data/signet/node-defaults.yaml +++ b/test/data/signet/node-defaults.yaml @@ -5,6 +5,9 @@ image: chain: signet +spec: + restartPolicy: Always + config: | debug=rpc debug=net diff --git a/test/signet_test.py b/test/signet_test.py index 5307ec9d9..68ec78713 100755 --- a/test/signet_test.py +++ b/test/signet_test.py @@ -38,8 +38,8 @@ def check_signet_miner(self): ) def block_one(): - for tank in ["tank-0001", "tank-0002"]: - height = int(self.warnet(f"bitcoin rpc {tank} getblockcount")) + for n in range(1, 11): + height = int(self.warnet(f"bitcoin rpc tank-{n} getblockcount")) if height != 1: return False return True diff --git a/test/test_base.py b/test/test_base.py index 3250ecd95..fbea5e79d 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -81,8 +81,11 @@ def output_reader(self, pipe, func): def wait_for_predicate(self, predicate, timeout=5 * 60, interval=5): self.log.debug(f"Waiting for predicate with timeout {timeout}s and interval {interval}s") while timeout > 0: - if predicate(): - return + try: + if predicate(): + return + except Exception: + pass sleep(interval) timeout -= interval import inspect