--- # Every task here is guarded by `when: not bitcoind_binary_exists.stat.exists`, # so on a host that already has the binary the whole download / verify / build # sequence skips — including the two `state: absent` deletions, which target # /opt/bitcoin-knots/{source,bitcoin-} and never the chain data in # /mnt/knots_data. - name: Check if bitcoind binary already exists stat: path: "{{ bitcoin_build_prefix }}/bin/bitcoind" register: bitcoind_binary_exists changed_when: false - name: Install gnupg for signature verification apt: name: gnupg state: present when: not bitcoind_binary_exists.stat.exists - name: Import Luke Dashjr's Bitcoin Knots signing key command: gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 90C8019E36C2E964 register: key_import changed_when: "'already in secret keyring' not in key_import.stdout and 'already in public keyring' not in key_import.stdout" when: not bitcoind_binary_exists.stat.exists failed_when: key_import.rc != 0 - name: Display imported key fingerprint command: gpg --fingerprint 90C8019E36C2E964 register: key_fingerprint changed_when: false when: not bitcoind_binary_exists.stat.exists - name: Download SHA256SUMS file get_url: url: "https://bitcoinknots.org/files/{{ bitcoin_version_major }}.x/{{ bitcoin_knots_version_short }}/SHA256SUMS" dest: "/tmp/bitcoin-knots-{{ bitcoin_knots_version_short }}-SHA256SUMS" mode: '0644' when: not bitcoind_binary_exists.stat.exists - name: Download SHA256SUMS.asc signature file get_url: url: "https://bitcoinknots.org/files/{{ bitcoin_version_major }}.x/{{ bitcoin_knots_version_short }}/SHA256SUMS.asc" dest: "/tmp/bitcoin-knots-{{ bitcoin_knots_version_short }}-SHA256SUMS.asc" mode: '0644' when: not bitcoind_binary_exists.stat.exists - name: Verify PGP signature on SHA256SUMS file command: gpg --verify /tmp/bitcoin-knots-{{ bitcoin_knots_version_short }}-SHA256SUMS.asc /tmp/bitcoin-knots-{{ bitcoin_knots_version_short }}-SHA256SUMS register: sha256sums_verification changed_when: false failed_when: false # Don't fail here - check for 'Good signature' in next task when: not bitcoind_binary_exists.stat.exists - name: Display SHA256SUMS verification result debug: msg: "{{ sha256sums_verification.stdout_lines + sha256sums_verification.stderr_lines }}" when: not bitcoind_binary_exists.stat.exists - name: Fail if SHA256SUMS signature verification failed fail: msg: "SHA256SUMS signature verification failed. Aborting build." when: not bitcoind_binary_exists.stat.exists and ('Good signature' not in sha256sums_verification.stdout and 'Good signature' not in sha256sums_verification.stderr) - name: Remove any existing tarball to force fresh download file: path: /tmp/bitcoin-{{ bitcoin_knots_version_short }}.tar.gz state: absent when: not bitcoind_binary_exists.stat.exists - name: Download Bitcoin Knots source tarball get_url: url: "{{ bitcoin_source_tarball_url }}" dest: "/tmp/bitcoin-{{ bitcoin_knots_version_short }}.tar.gz" mode: '0644' validate_certs: yes force: yes when: not bitcoind_binary_exists.stat.exists - name: Calculate SHA256 checksum of downloaded tarball command: sha256sum /tmp/bitcoin-{{ bitcoin_knots_version_short }}.tar.gz register: tarball_checksum changed_when: false when: not bitcoind_binary_exists.stat.exists - name: Extract expected checksum from SHA256SUMS file shell: grep "bitcoin-{{ bitcoin_knots_version_short }}.tar.gz" /tmp/bitcoin-knots-{{ bitcoin_knots_version_short }}-SHA256SUMS | awk '{print $1}' register: expected_checksum changed_when: false when: not bitcoind_binary_exists.stat.exists failed_when: expected_checksum.stdout == "" - name: Display checksum comparison debug: msg: - "Expected: {{ expected_checksum.stdout | trim }}" - "Actual: {{ tarball_checksum.stdout.split()[0] }}" when: not bitcoind_binary_exists.stat.exists - name: Verify tarball checksum matches SHA256SUMS fail: msg: "Tarball checksum mismatch! Expected {{ expected_checksum.stdout | trim }}, got {{ tarball_checksum.stdout.split()[0] }}" when: not bitcoind_binary_exists.stat.exists and expected_checksum.stdout | trim != tarball_checksum.stdout.split()[0] - name: Remove existing source directory if it exists (to force fresh extraction) file: path: "{{ bitcoin_knots_source_dir }}" state: absent when: not bitcoind_binary_exists.stat.exists - name: Remove extracted directory if it exists (from previous runs) file: path: "{{ bitcoin_knots_dir }}/bitcoin-{{ bitcoin_knots_version_short }}" state: absent when: not bitcoind_binary_exists.stat.exists - name: Extract verified source tarball unarchive: src: /tmp/bitcoin-{{ bitcoin_knots_version_short }}.tar.gz dest: "{{ bitcoin_knots_dir }}" remote_src: yes when: not bitcoind_binary_exists.stat.exists - name: Check if extracted directory exists stat: path: "{{ bitcoin_knots_dir }}/bitcoin-{{ bitcoin_knots_version_short }}" register: extracted_dir_stat changed_when: false when: not bitcoind_binary_exists.stat.exists - name: Rename extracted directory to expected name command: mv "{{ bitcoin_knots_dir }}/bitcoin-{{ bitcoin_knots_version_short }}" "{{ bitcoin_knots_source_dir }}" when: not bitcoind_binary_exists.stat.exists and extracted_dir_stat.stat.exists - name: Check if CMakeLists.txt exists stat: path: "{{ bitcoin_knots_source_dir }}/CMakeLists.txt" register: cmake_exists changed_when: false when: not bitcoind_binary_exists.stat.exists - name: Create CMake build directory file: path: "{{ bitcoin_knots_source_dir }}/build" state: directory mode: '0755' when: not bitcoind_binary_exists.stat.exists and cmake_exists.stat.exists | default(false) - name: Configure Bitcoin Knots build with CMake command: > cmake -DCMAKE_INSTALL_PREFIX={{ bitcoin_build_prefix }} -DBUILD_BITCOIN_WALLET=OFF -DCMAKE_BUILD_TYPE=Release -DWITH_ZMQ=ON .. args: chdir: "{{ bitcoin_knots_source_dir }}/build" when: not bitcoind_binary_exists.stat.exists and cmake_exists.stat.exists | default(false) register: configure_result changed_when: true - name: Verify CMake enabled ZMQ shell: | set -e cd "{{ bitcoin_knots_source_dir }}/build" cmake -LAH .. | grep -iE 'ZMQ|WITH_ZMQ|ENABLE_ZMQ|USE_ZMQ' when: not bitcoind_binary_exists.stat.exists and cmake_exists.stat.exists | default(false) register: zmq_check changed_when: false - name: Fail if CMakeLists.txt not found fail: msg: "CMakeLists.txt not found in {{ bitcoin_knots_source_dir }}. Cannot build Bitcoin Knots." when: not bitcoind_binary_exists.stat.exists and not (cmake_exists.stat.exists | default(false)) - name: Build Bitcoin Knots with CMake (this may take 30-60+ minutes) command: cmake --build . -j{{ bitcoin_build_jobs }} args: chdir: "{{ bitcoin_knots_source_dir }}/build" when: not bitcoind_binary_exists.stat.exists and cmake_exists.stat.exists | default(false) async: 3600 poll: 0 register: build_result changed_when: true - name: Check build status async_status: jid: "{{ build_result.ansible_job_id }}" register: build_job_result until: build_job_result.finished retries: 120 delay: 60 when: not bitcoind_binary_exists.stat.exists and build_result.ansible_job_id is defined - name: Fail if build failed fail: msg: "Bitcoin Knots build failed: {{ build_job_result.msg }}" when: not bitcoind_binary_exists.stat.exists and build_result.ansible_job_id is defined and build_job_result.failed | default(false) - name: Install Bitcoin Knots binaries command: cmake --install . args: chdir: "{{ bitcoin_knots_source_dir }}/build" when: not bitcoind_binary_exists.stat.exists and cmake_exists.stat.exists | default(false) changed_when: true - name: Verify bitcoind binary exists stat: path: "{{ bitcoin_build_prefix }}/bin/bitcoind" register: bitcoind_installed changed_when: false - name: Verify bitcoin-cli binary exists stat: path: "{{ bitcoin_build_prefix }}/bin/bitcoin-cli" register: bitcoin_cli_installed changed_when: false - name: Fail if binaries not found fail: msg: "Bitcoin Knots binaries not found after installation" when: not bitcoind_installed.stat.exists or not bitcoin_cli_installed.stat.exists