diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5cae564e4d..858a2cafdc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -477,11 +477,11 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_previous_releases.sh' - - name: 'CentOS, depends, gui' + - name: 'Alpine (musl), depends, gui' cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' fallback-runner: 'ubuntu-24.04' timeout-minutes: 120 - file-env: './ci/test/00_setup_env_native_centos.sh' + file-env: './ci/test/00_setup_env_native_alpine_musl.sh' - name: 'tidy' cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' diff --git a/ci/test/00_setup_env_native_centos.sh b/ci/test/00_setup_env_native_alpine_musl.sh similarity index 57% rename from ci/test/00_setup_env_native_centos.sh rename to ci/test/00_setup_env_native_alpine_musl.sh index 998ddaf45f8..094709ff828 100755 --- a/ci/test/00_setup_env_native_centos.sh +++ b/ci/test/00_setup_env_native_alpine_musl.sh @@ -6,10 +6,10 @@ export LC_ALL=C.UTF-8 -export CONTAINER_NAME=ci_native_centos -export CI_IMAGE_NAME_TAG="quay.io/centos/centos:stream10" -export CI_BASE_PACKAGES="gcc-c++ glibc-devel libstdc++-devel ccache make ninja-build git python3 python3-pip which patch xz procps-ng rsync coreutils bison e2fsprogs cmake dash" -export PIP_PACKAGES="pyzmq pycapnp" +export CONTAINER_NAME=ci_native_alpine_musl +export CI_IMAGE_NAME_TAG="mirror.gcr.io/alpine:3.22" +export CI_BASE_PACKAGES="build-base musl-dev pkgconf curl ccache make ninja git python3 py3-pip which patch xz procps rsync util-linux bison e2fsprogs cmake dash linux-headers" +export PIP_PACKAGES="--break-system-packages pyzmq pycapnp" export DEP_OPTS="DEBUG=1" export GOAL="install" export BITCOIN_CONFIG="\ diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh index ce460987901..144b9ab253f 100755 --- a/ci/test/01_base_install.sh +++ b/ci/test/01_base_install.sh @@ -32,16 +32,17 @@ if [ -n "${APT_LLVM_V}" ]; then ) fi -if [[ $CI_IMAGE_NAME_TAG == *centos* ]]; then - bash -c "dnf -y install epel-release" - # The ninja-build package is available in the CRB repository. - bash -c "dnf -y --allowerasing --enablerepo crb install $CI_BASE_PACKAGES $PACKAGES" +if [[ $CI_IMAGE_NAME_TAG == *alpine* ]]; then + ${CI_RETRY_EXE} apk update + # shellcheck disable=SC2086 + ${CI_RETRY_EXE} apk add --no-cache $CI_BASE_PACKAGES $PACKAGES elif [ "$CI_OS_NAME" != "macos" ]; then if [[ -n "${APPEND_APT_SOURCES_LIST}" ]]; then echo "${APPEND_APT_SOURCES_LIST}" >> /etc/apt/sources.list fi ${CI_RETRY_EXE} apt-get update - ${CI_RETRY_EXE} bash -c "apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $CI_BASE_PACKAGES" + # shellcheck disable=SC2086 + ${CI_RETRY_EXE} apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $CI_BASE_PACKAGES fi if [ -n "${APT_LLVM_V}" ]; then diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index 05e4d8fd54a..9353f624294 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -99,8 +99,8 @@ else fi if [ -z "$NO_DEPENDS" ]; then - if [[ $CI_IMAGE_NAME_TAG == *centos* ]]; then - SHELL_OPTS="CONFIG_SHELL=/bin/dash" + if [[ $CI_IMAGE_NAME_TAG == *alpine* ]]; then + SHELL_OPTS="CONFIG_SHELL=/usr/bin/dash" else SHELL_OPTS="CONFIG_SHELL=" fi diff --git a/ci/test_imagefile b/ci/test_imagefile index f9cf3187a25..a0e1714ed5f 100644 --- a/ci/test_imagefile +++ b/ci/test_imagefile @@ -17,4 +17,7 @@ ENV BASE_ROOT_DIR=${BASE_ROOT_DIR} COPY ./ci/retry/retry /usr/bin/retry COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh /ci_container_base/ci/test/ +# Bash is required, so install it when missing +RUN sh -c "bash -c 'true' || ( apk update && apk add --no-cache bash )" + RUN ["bash", "-c", "cd /ci_container_base/ && set -o errexit && source ./ci/test/00_setup_env.sh && ./ci/test/01_base_install.sh"] diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index d1c627bb3ce..005f1517f4e 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -210,7 +210,7 @@ - + IBeamCursor @@ -1872,6 +1872,11 @@ PlainCopyTextEdit QTextEdit + + NetworkName + QLabel +
qt/rpcconsole.h
+
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 958c82fda22..66128dcf6a6 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -57,6 +57,9 @@ const int INITIAL_TRAFFIC_GRAPH_MINS = 30; const QSize FONT_RANGE(4, 40); const char fontSizeSettingsKey[] = "consoleFontSize"; +const std::string DEFAULT_CHALLENGE_STRING = + "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"; + const struct { const char *url; const char *source; @@ -717,6 +720,39 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ ui->blocksDir->setText(model->blocksDir()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().GetChainTypeString())); + ui->networkName->setWordWrap(true); + + if (Params().GetChainTypeString() == "signet") { + std::vector vChallenge = Params().GetConsensus().signet_challenge; + std::string challengeString = HexStr(vChallenge); + if (challengeString != DEFAULT_CHALLENGE_STRING) { + LogDebug(BCLog::QT, "rpcconsole:challengeString=%s\n", challengeString); + if (challengeString.length() > 16) { // a sane minimum + std::string challenge_fingerprint = challengeString.substr(0, 8); + const QString title = tr("Node window - [signet] (%1)").arg(QString::fromStdString(challenge_fingerprint)); + // display fingerprint in Node window title + this->setWindowTitle(title); + } else { + // A trivial challenge is supported. Example: signetchallenge=51 + std::string challenge_fingerprint = challengeString.substr(0, challengeString.length()); + const QString title = tr("Node window - [signet] (%1)").arg(QString::fromStdString(challenge_fingerprint)); + // display fingerprint in Node window title + this->setWindowTitle(title); + } + if (challengeString.length() > (size_t)ui->networkName->width()) { + challengeString.insert(0, "\n"); // break after Signet: + challengeString.insert(65, "\n"); // then split at (130/2) + } + ui->networkName->setToolTip( + tr("%1").arg(QString::fromStdString(challengeString))); + ui->networkName->setText( + tr("%1\nChallenge: %2").arg("Signet").arg(QString::fromStdString(challengeString))); + } else { + ui->networkName->setText(tr("Signet: Default")); + ui->networkName->setToolTip(QString()); + this->setWindowTitle(tr("[signet] Default")); + } + } //Setup autocomplete and attach it QStringList wordList; diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index fe2955cc26b..a03cf595214 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -15,6 +15,8 @@ #include #include +#include +#include #include #include #include @@ -210,4 +212,56 @@ class PlainCopyTextEdit : public QTextEdit { } }; +class NetworkName : public QLabel +{ + Q_OBJECT + +public: + explicit NetworkName(QWidget *parent = nullptr) : QLabel(parent) {} + + void setText(const QString& text) { + m_fullText = text; + recalculateElidedText(); + } + + const QString& fullText() const { return m_fullText; } + QString selectedText() const { + return m_fullText; + } + +protected: + void resizeEvent(QResizeEvent *event) override { + QLabel::resizeEvent(event); + recalculateElidedText(); + } + + // Provide the full challenge when Copy&Paste + QMimeData* createMimeDataFromSelection() const { + auto md = new QMimeData(); + md->setText(m_fullText); + return md; + } + +private: + QString m_fullText; + + void recalculateElidedText() { + if (m_fullText.isEmpty()) { + QLabel::setText(QString()); + return; + } + + QFontMetrics fm(font()); + int availableWidth = width()-1; + //int availableWidth = contentsRect().width()-1; + + QString elidedText = fm.elidedText(m_fullText, Qt::ElideMiddle, availableWidth); + + if (QLabel::text() != elidedText) { + QLabel::setText(elidedText); + //QLabel::setText(m_fullText); + } + } +}; + #endif // BITCOIN_QT_RPCCONSOLE_H