bitcoinkernel 0.2.0

Safe Rust bindings to libbitcoinkernel
Documentation
name: Rust CI

on:
  push:
  pull_request:

env:
  CARGO_TERM_COLOR: always

jobs:
  msrv-check:
    name: Build with MSRV
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Install Rust MSRV
      uses: dtolnay/rust-toolchain@master
      with:
        # Set this to your MSRV as specified in Cargo.toml
        toolchain: 1.71.0

    - name: Install Boost library
      run: |
        sudo apt-get update
        sudo apt-get install -y libboost-all-dev

    - name: Cache dependencies
      uses: Swatinem/rust-cache@v2

    - name: Build with MSRV
      run: |
        # Ensure we're using the right version
        rustc --version
        # Build the project
        cargo build --all-features
 
    - name: Run tests with MSRV
      run: cargo test --all-features

  build:
    name: Build and Test
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Install Rust toolchain
      uses: actions-rs/toolchain@v1
      with:
        profile: minimal
        toolchain: stable
        override: true
        components: rustfmt

    - name: Cache dependencies
      uses: Swatinem/rust-cache@v2

    - name: Install Boost library
      run: |
        sudo apt-get update
        sudo apt-get install -y libboost-all-dev

    - name: Build
      run: cargo build -vv

    - name: Build example binary
      run: |
        cd examples
        cargo build --verbose

    - name: Check formatting
      run: cargo fmt -- --check

    - name: Check documentation
      env:
        RUSTDOCFLAGS: "-D warnings"
      run: cargo doc --no-deps --all-features --document-private-items

    - name: Install llvm-tools for coverage
      run: rustup component add llvm-tools-preview

    - name: Install cargo-llvm-cov
      run: cargo install cargo-llvm-cov --locked --version 0.6.19

    - name: Run tests with coverage
      run: cargo llvm-cov --all-features --workspace --html --verbose

    - name: Upload coverage report
      uses: actions/upload-artifact@v4
      with:
        name: coverage-report
        path: target/llvm-cov/html/

    - name: Install Valgrind
      run: |
        sudo apt-get update
        sudo apt-get install -y valgrind

    - name: Run tests with Valgrind
      run: |
        find target/debug/deps -type f -executable -name "test-*" -not -name "*.so" -not -name "*.d" | xargs -I {} valgrind --leak-check=full --show-leak-kinds=all  --errors-for-leak-kinds=definite --suppressions=valgrind.supp --error-exitcode=1 {}

  windows-build:
    name: Build and Test on Windows
    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v3

    - name: Install Rust toolchain
      uses: actions-rs/toolchain@v1
      with:
        profile: minimal
        toolchain: stable
        override: true
        components: rustfmt

    - name: Cache dependencies
      uses: Swatinem/rust-cache@v2

    - name: Install Boost library
      run: |
        git clone https://github.com/microsoft/vcpkg.git
        cd vcpkg
        .\bootstrap-vcpkg.bat
        .\vcpkg install boost-multi-index:x64-windows-static boost-headers:x64-windows-static
        echo "VCPKG_ROOT=$env:GITHUB_WORKSPACE\vcpkg" | Out-File -FilePath $env:GITHUB_ENV -Append
        echo "$env:GITHUB_WORKSPACE\vcpkg\installed\x64-windows-static\lib" | Out-File -FilePath $env:GITHUB_PATH -Append

    - name: Set environment variables for static linking
      run: |
        echo "BOOST_ROOT=$env:GITHUB_WORKSPACE\vcpkg\installed\x64-windows-static" | Out-File -FilePath $env:GITHUB_ENV -Append
        echo "BOOST_INCLUDEDIR=$env:GITHUB_WORKSPACE\vcpkg\installed\x64-windows-static\include" | Out-File -FilePath $env:GITHUB_ENV -Append
        echo "BOOST_LIBRARYDIR=$env:GITHUB_WORKSPACE\vcpkg\installed\x64-windows-static\lib" | Out-File -FilePath $env:GITHUB_ENV -Append

    - name: Run tests
      run: cargo test -vv

  linux-aarch64:
    name: Build and Test on Linux ARM64
    runs-on: ubuntu-24.04-arm

    steps:
    - uses: actions/checkout@v3

    - name: Install Rust toolchain
      uses: actions-rs/toolchain@v1
      with:
        profile: minimal
        toolchain: stable
        override: true
        components: rustfmt

    - name: Cache dependencies
      uses: Swatinem/rust-cache@v2

    - name: Install Boost library
      run: |
        sudo apt-get update
        sudo apt-get install -y libboost-all-dev

    - name: Build and test
      run: cargo test -vv

  macos-build:
    name: Build and Test on macOS
    runs-on: macos-latest

    steps:
    - uses: actions/checkout@v3

    - name: Install Rust toolchain
      uses: actions-rs/toolchain@v1
      with:
        profile: minimal
        toolchain: stable
        override: true
        components: rustfmt

    - name: Cache dependencies
      uses: Swatinem/rust-cache@v2

    - name: Install Boost library
      run: |
        brew install boost

    - name: Build and test
      run: cargo test -vv

  fuzz-corpus:
    name: Verify Fuzz Corpus
    runs-on: ubuntu-latest
    timeout-minutes: 15
    strategy:
      fail-fast: false
      matrix:
        target:
          - block_roundtrip
          - chainman_process_block
          - script_verify
          - transaction_roundtrip

    steps:
      - name: Checkout rust-bitcoinkernel
        uses: actions/checkout@v3

      - name: Checkout qa-assets corpus
        uses: actions/checkout@v3
        with:
          repository: alexanderwiederin/qa-assets
          path: qa-assets

      - name: Install Rust nightly
        uses: dtolnay/rust-toolchain@nightly

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Install Boost library
        run: |
          sudo apt-get update
          sudo apt-get install -y libboost-all-dev

      - name: Install cargo-fuzz
        run: cargo install cargo-fuzz

      - name: Verify corpus exists
        run: |
          CORPUS_DIR="qa-assets/fuzz_corpora/${{ matrix.target }}"

          if [ ! -d "$CORPUS_DIR" ]; then
            echo "Error: Corpus directory does not exist: $CORPUS_DIR"
            echo ""
            echo "Please create corpus data for ${{ matrix.target }}"
            exit 1
          fi

          FILE_COUNT=$(find "$CORPUS_DIR" -type f | wc -l)

          if [ "$FILE_COUNT" -eq 0 ]; then
            echo "Error: Corpus directory is empty: $CORPUS_DIR"
            echo ""
            echo "Please add corpus files for ${{ matrix.target }}"
            exit 1
          fi

          echo "✓ Found $FILE_COUNT corpus files for ${{ matrix.target }}"

      - name: Verify corpus
        env:
          RUSTFLAGS: "-Zsanitizer=address"
          ASAN_OPTIONS: "detect_leaks=1"
        run: |
          CORPUS_DIR="qa-assets/fuzz_corpora/${{ matrix.target }}"

          echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
          echo "Testing ${{ matrix.target }} corpus"
          echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

          FILE_COUNT=$(find "$CORPUS_DIR" -type f | wc -l)
          echo "Testing $FILE_COUNT corpus files"
          echo ""

          # Test all corpus files without generating new inputs
          cargo fuzz run "${{ matrix.target }}" \
            "$CORPUS_DIR" \
            -- \
            -runs=0 \
            -timeout=10 \
            -rss_limit_mb=2048

          echo ""
          echo "✓ All $FILE_COUNT corpus files passed!"

      - name: Upload crash artifacts
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: crashes-${{ matrix.target }}
          path: fuzz/artifacts/${{ matrix.target }}/
          if-no-files-found: ignore