From ab132c9f0b73a96bde764aae94a032a2e68dd18e Mon Sep 17 00:00:00 2001 From: Jose Storopoli Date: Sat, 6 Jan 2024 04:56:10 -0300 Subject: [PATCH] ci: move to Nix (simpler, easy to maintain version) --- .github/workflows/audit.yml | 13 +- .github/workflows/code_coverage.yml | 37 ++-- .github/workflows/cont_integration.yml | 167 +++++++-------- .github/workflows/nightly_docs.yml | 30 ++- .github/workflows/update_flake_lock.yml | 21 ++ .gitignore | 9 +- .typos.toml | 7 + CONTRIBUTING.md | 33 ++- Cargo.toml | 8 + NIX.md | 138 ++++++++++++ README.md | 14 +- ci/commits_verify_signature.sh | 16 ++ crates/bdk/Cargo.toml | 3 + crates/bitcoind_rpc/Cargo.toml | 2 +- crates/bitcoind_rpc/README.md | 4 + crates/bitcoind_rpc/tests/test_emitter.rs | 5 +- crates/chain/Cargo.toml | 4 +- crates/esplora/Cargo.toml | 2 +- crates/esplora/README.md | 5 + crates/esplora/tests/async_ext.rs | 16 +- crates/esplora/tests/blocking_ext.rs | 19 +- flake.lock | 244 ++++++++++++++++++++++ flake.nix | 211 +++++++++++++++++++ 23 files changed, 836 insertions(+), 172 deletions(-) create mode 100644 .github/workflows/update_flake_lock.yml create mode 100644 .typos.toml create mode 100644 NIX.md create mode 100755 ci/commits_verify_signature.sh create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 6143cca822..3feb0288b0 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -3,17 +3,16 @@ name: Audit on: push: paths: - - '**/Cargo.toml' - - '**/Cargo.lock' + - "**/Cargo.toml" + - "**/Cargo.lock" schedule: - - cron: '0 0 * * 0' # Once per week + - cron: "0 0 * * 0" # Once per week jobs: - security_audit: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions-rs/audit-check@v1 with: - token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 54020bb90d..90148bc0d6 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -6,27 +6,18 @@ jobs: Codecov: name: Code Coverage runs-on: ubuntu-latest - env: - RUSTFLAGS: "-Cinstrument-coverage" - RUSTDOCFLAGS: "-Cinstrument-coverage" - LLVM_PROFILE_FILE: "./target/coverage/%p-%m.profraw" - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install lcov tools - run: sudo apt-get install lcov -y - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal - components: llvm-tools-preview + - name: checkout + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 - name: Rust Cache - uses: Swatinem/rust-cache@v2.2.1 + uses: Swatinem/rust-cache@v2 + # Code Coverage - name: Install grcov - run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo install grcov; fi + run: nix develop -L ".#coverage" --command cargo install grcov # TODO: re-enable the hwi tests - name: Build simulator image run: docker build -t hwi/ledger_emulator ./ci -f ci/Dockerfile.ledger @@ -35,23 +26,23 @@ jobs: - name: Install Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: "3.9" - name: Install python dependencies run: pip install hwi==2.1.1 protobuf==3.20.1 - name: Test - run: cargo test --all-features + run: nix develop ".#coverage" -L -command cargo test --all-features - name: Make coverage directory run: mkdir coverage - name: Run grcov - run: grcov . --binary-path ./target/debug/ -s . -t lcov --branch --ignore-not-existing --keep-only '**/crates/**' --ignore '**/tests/**' --ignore '**/examples/**' -o ./coverage/lcov.info + run: nix develop ".#coverage" -L --command grcov . --binary-path ./target/debug/ -s . -t lcov --branch --ignore-not-existing --keep-only '**/crates/**' --ignore '**/tests/**' --ignore '**/examples/**' -o ./coverage/lcov.info - name: Generate HTML coverage report - run: genhtml -o coverage-report.html --ignore-errors source ./coverage/lcov.info + run: nix develop ".#coverage" -L --command genhtml -o coverage-report.html --ignore-errors source ./coverage/lcov.info - name: Coveralls upload uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: coverage-report path: coverage-report.html diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index 9db71a9d01..35399a3466 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -3,127 +3,102 @@ on: [push, pull_request] name: CI jobs: + self-care: + name: Flake self-check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Check Nix flake inputs + uses: DeterminateSystems/flake-checker-action@v5 + with: + fail-mode: true + + pre-commit-checks: + name: "Pre-commit checks: cargo fmt/clippy, typos, pgp-signed and conventional commits" + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: Pre-commit checks + run: nix develop -L . --command pre-commit run --all-files build-test: - name: Build and test + name: Build, test, check Rust runs-on: ubuntu-latest strategy: matrix: rust: - - version: stable - clippy: true - - version: 1.63.0 # MSRV + - "" # empty means default + - msrv features: - --no-default-features - --all-features steps: - name: checkout - uses: actions/checkout@v2 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.rust.version }} - override: true - profile: minimal + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 - name: Rust Cache - uses: Swatinem/rust-cache@v2.2.1 - - name: Pin dependencies for MSRV - if: matrix.rust.version == '1.63.0' - run: | - cargo update -p zstd-sys --precise "2.0.8+zstd.1.5.5" - cargo update -p time --precise "0.3.20" - cargo update -p jobserver --precise "0.1.26" - cargo update -p home --precise "0.5.5" - - name: Build - run: cargo build ${{ matrix.features }} - - name: Test - run: cargo test ${{ matrix.features }} + uses: Swatinem/rust-cache@v2 + - name: build + run: nix develop -L ".#${{ matrix.rust }}" --command cargo build ${{ matrix.features }} + - name: test + run: nix develop -L ".#${{ matrix.rust }}" --command cargo test ${{ matrix.features }} check-no-std: name: Check no_std runs-on: ubuntu-latest + strategy: + matrix: + rust: + - "" # empty means default + - msrv steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal - # target: "thumbv6m-none-eabi" + - name: checkout + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 - name: Rust Cache - uses: Swatinem/rust-cache@v2.2.1 + uses: Swatinem/rust-cache@v2 + # TODO "--target thumbv6m-none-eabi" should work but currently does not - name: Check bdk_chain - working-directory: ./crates/chain - # TODO "--target thumbv6m-none-eabi" should work but currently does not - run: cargo check --no-default-features --features bitcoin/no-std,miniscript/no-std,hashbrown + run: nix develop -L ".#${{ matrix.rust }}" --command cargo check -p bdk_chain --no-default-features --features bitcoin/no-std,miniscript/no-std,hashbrown - name: Check bdk - working-directory: ./crates/bdk - # TODO "--target thumbv6m-none-eabi" should work but currently does not - run: cargo check --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown + run: nix develop -L ".#${{ matrix.rust }}" --command cargo check -p bdk --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown - name: Check esplora - working-directory: ./crates/esplora - # TODO "--target thumbv6m-none-eabi" should work but currently does not - run: cargo check --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown + run: nix develop -L ".#${{ matrix.rust }}" --command cargo check -p bdk_esplora --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown check-wasm: name: Check WASM - runs-on: ubuntu-20.04 - env: - CC: clang-10 - CFLAGS: -I/usr/include + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - "" # empty means default + - msrv + target: + - wasm32-unknown-unknown steps: - - name: Checkout - uses: actions/checkout@v2 - # Install a recent version of clang that supports wasm32 - - run: wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - || exit 1 - - run: sudo apt-get update || exit 1 - - run: sudo apt-get install -y libclang-common-10-dev clang-10 libc6-dev-i386 || exit 1 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal - target: "wasm32-unknown-unknown" + - name: checkout + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 - name: Rust Cache - uses: Swatinem/rust-cache@v2.2.1 + uses: Swatinem/rust-cache@v2 + # TODO "--target thumbv6m-none-eabi" should work but currently does not - name: Check bdk - working-directory: ./crates/bdk - run: cargo check --target wasm32-unknown-unknown --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown,dev-getrandom-wasm + run: nix develop -L ".#${{ matrix.rust }}" --command cargo check -p bdk --target ${{ matrix.target }} --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown,dev-getrandom-wasm - name: Check esplora - working-directory: ./crates/esplora - run: cargo check --target wasm32-unknown-unknown --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown,async - - fmt: - name: Rust fmt - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal - components: rustfmt - - name: Check fmt - run: cargo fmt --all -- --config format_code_in_doc_comments=true --check - - clippy_check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - components: clippy - override: true - - name: Rust Cache - uses: Swatinem/rust-cache@v2.2.1 - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features --all-targets -- -D warnings + run: nix develop -L ".#${{ matrix.rust }}" --command cargo check -p bdk_esplora --target ${{ matrix.target }} --no-default-features --features bitcoin/no-std,miniscript/no-std,bdk_chain/hashbrown,async diff --git a/.github/workflows/nightly_docs.yml b/.github/workflows/nightly_docs.yml index 0321cc5337..ba8d6650c2 100644 --- a/.github/workflows/nightly_docs.yml +++ b/.github/workflows/nightly_docs.yml @@ -7,34 +7,30 @@ jobs: name: Build docs runs-on: ubuntu-latest steps: - - name: Checkout sources - uses: actions/checkout@v2 - - name: Set default toolchain - run: rustup default nightly-2022-12-14 - - name: Set profile - run: rustup set profile minimal - - name: Update toolchain - run: rustup update + - name: checkout + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@v2 - name: Rust Cache - uses: Swatinem/rust-cache@v2.2.1 + uses: Swatinem/rust-cache@v2 - name: Build docs - run: cargo doc --no-deps - env: - RUSTDOCFLAGS: '--cfg docsrs -Dwarnings' + run: nix develop -L '.#nightly' --command cargo doc --no-deps - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: built-docs path: ./target/doc/* publish_docs: - name: 'Publish docs' + name: "Publish docs" if: github.ref == 'refs/heads/master' needs: [build_docs] runs-on: ubuntu-latest steps: - name: Checkout `bitcoindevkit.org` - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: ssh-key: ${{ secrets.DOCS_PUSH_SSH_KEY }} repository: bitcoindevkit/bitcoindevkit.org @@ -44,14 +40,14 @@ jobs: - name: Remove old latest run: rm -rf ./docs/.vuepress/public/docs-rs/bdk/nightly/latest - name: Download built docs - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: built-docs path: ./docs/.vuepress/public/docs-rs/bdk/nightly/latest - name: Configure git run: git config user.email "github-actions@github.com" && git config user.name "github-actions" - name: Commit - continue-on-error: true # If there's nothing to commit this step fails, but it's fine + continue-on-error: true # If there's nothing to commit this step fails, but it's fine run: git add ./docs/.vuepress/public/docs-rs && git commit -m "Publish autogenerated nightly docs" - name: Push run: git push origin master diff --git a/.github/workflows/update_flake_lock.yml b/.github/workflows/update_flake_lock.yml new file mode 100644 index 0000000000..4ea2cea068 --- /dev/null +++ b/.github/workflows/update_flake_lock.yml @@ -0,0 +1,21 @@ +name: Update Flake Lock File +on: + workflow_dispatch: # allows manual triggering + schedule: + - cron: "0 0 1 * *" # runs monthly on day 1 at 00:00 + +jobs: + lockfile: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v5 + - name: Update flake.lock + uses: DeterminateSystems/update-flake-lock@v20 + with: + pr-title: "ci: update flake.lock" # Title of PR to be created + pr-labels: | # Labels to be set on the PR + dependencies + automated diff --git a/.gitignore b/.gitignore index 95285763a3..9edd413f62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,16 @@ +# Added by Cargo /target Cargo.lock -/.vscode +# Dev environment +/.vscode *.swp .idea # Example persisted files. *.db + +# Nix +/result +# pre-commit-hooks.nix +.pre-commit-config.yaml diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 0000000000..72da312faa --- /dev/null +++ b/.typos.toml @@ -0,0 +1,7 @@ +[default] +extend-ignore-re = [ + "\\b[0-9A-Za-z+/]{91}(=|==)?\\b", # base64 strings + "[0-9a-fA-F]{7,}", # git commit hashes + "\\b[0-9A-Za-z+/]{33,}(=|==)?\\b", # SHA/tpub/adresses etc strings + "flate2", # crate +] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a83ccf575..a4cff173c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ Any bug may cost users real money. That being said, we deeply welcome people contributing for the first time to an open source project or picking up Rust while contributing. Don't be shy, you'll learn. -Communications Channels +Communication Channels ----------------------- Communication about BDK happens primarily on the [BDK Discord](https://discord.gg/dstn4dQ). @@ -31,8 +31,8 @@ facilitates social contribution, easy testing and peer review. To contribute a patch, the workflow is as follows: 1. Fork Repository - 2. Create topic branch - 3. Commit patches + 1. Create topic branch + 1. Commit patches In general commits should be atomic and diffs should be easy to read. For this reason do not mix any formatting fixes or code moves with actual code @@ -48,15 +48,36 @@ hesitate to split it into multiple small, focused PRs. The Minimal Supported Rust Version is **1.57.0** (enforced by our CI). -Commits should cover both the issue fixed and the solution's rationale. -These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in mind. Commit messages should follow the ["Conventional Commits 1.0.0"](https://www.conventionalcommits.org/en/v1.0.0/) to make commit histories easier to read by humans and automated tools. - To facilitate communication with other contributors, the project is making use of GitHub's "assignee" field. First check that no one is assigned and then comment suggesting that you're working on it. If someone is already assigned, don't hesitate to ask if the assigned party or previous commenter are still working on it if it has been awhile. +Our CI can be replicated locally with Nix. +Just run `nix flake check`. +Our Nix setup can greatly increase developer experience +and onboarding of new contributors. +Please check the [`NIX.md`](NIX.md) for details +on how to install Nix and why we use it. + +Commit policy +------------- + +Commits should cover both the issue fixed and the solution's rationale. +These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in mind. + +We enforce two commit styles in our CI: + +1. Commits should be signed with GPG using a key with a valid email address. +1. Commit messages should follow the ["Conventional Commits 1.0.0"](https://www.conventionalcommits.org/en/v1.0.0/) + to make commit histories easier to read by humans and automated tools. + Commits starting with `Merge ...` which GitHub automatically generates + are exempt from this rule. + +You can use Nix to automatically and easily check locally these rules before commit and push events. +Please check the [`NIX.md`](NIX.md) for details. + Deprecation policy ------------------ diff --git a/Cargo.toml b/Cargo.toml index b190ba88fb..975df9ad28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,11 @@ members = [ [workspace.package] authors = ["Bitcoin Dev Kit Developers"] + +[profile.dev] + +[profile.ci] +inherits = "dev" +debug = 1 +incremental = false +lto = "off" diff --git a/NIX.md b/NIX.md new file mode 100644 index 0000000000..917d8da73e --- /dev/null +++ b/NIX.md @@ -0,0 +1,138 @@ +# BDK's Nix Guidelines + +This document outlines: + +1. What is Nix and how to install. +1. BDK's Nix-based tests and CI. +1. Developer best-practices with Nix. +1. How to run replicate CI tests locally. + +## Nix + +We use [Nix](https://nixos.org/) as the CI tool for BDK and also as a +development environment for the project. +Nix is purely functional. +Everything is described as an expression/function, +taking some inputs and producing deterministic outputs. +This guarantees reproducible results and makes caching everything easy. +Nix expressions are lazy. Anything described in Nix code will only be executed +if some other expression needs its results. +This is very powerful but somewhat unnatural for developers not familiar +with functional programming. + +There are several resources to get started with Nix: + +- [NixOS Wiki](https://nixos.wiki/). +- [Nix Reference Manual](https://nixos.org/manual/nix/stable/). +- [`nixpkgs` Manual](https://nixos.org/manual/nixpkgs/stable/). +- [Official documentation for getting things done with Nix](https://nix.dev/). + +There's also the [`nix-bitcoin` project](https://nixbitcoin.org/). + +To install Nix please follow the [official Nix documentation](https://nixos.org/manual/nix/stable/installation/installation.html). +You may need to enable Flakes support, check the instructions at [NixOS Wiki entry on Flakes](https://nixos.wiki/wiki/Flakes). + +## Why are we using Nix + +We want to make BDK's development easier. +This means two things: + +1. Enhance developer experience. +1. Facilitate onboarding of new contributors. + +Both of these can be accomplished with Nix. + +BDK has many crates in the workspace, +and proper development and testing needs dependencies to be installed, +and environment variables to be set. +This can be daunting for new contributors. + +BDK needs several Rust versions with different compilation targets. +This can be cumbersome to install, but also needs proper maintainability, +since these versions need to be updated frequently. + +BDK enforces commit styles and commit policies (please check [CONTRIBUTING.md](CONTRIBUTING.md)). +This is difficult to enforce locally +and can be a source of frustration during contribution reviews, +potentially leading to a lot of wasted time and pushing new contributors away. + +Finally, BDK has a lot of tests and checks. +It is difficult to replicate these locally. + +All the above can easily be accomplished with Nix. +Nix is available for macOS, Linux, and Windows; +while also being easy to install. +Nix has a rich [community](https://nixos.org/community/) and one can find help +on the [Nix's Forums](https://discourse.nixos.org/), +[Nix's Discord](https://discord.gg/RbvHtGa), +and [Nix's Matrix channel](https://matrix.to/#/#community:nixos.org). +Additionally, Nix issues and errors can be searched in any search engine, +and in the [Nix's stackoverflow](https://stackoverflow.com/questions/tagged/nix+or+nixpkgs+or+nixos+or+nixops). + +## BDK's Nix-based tests and CI + +BDK's tests and checks are run using Nix. +If you want to run the tests locally, you can do so with: + +```shell +nix develop -L . +pre-commit run --all-files +``` + +The `-L` flag prints full build logs on standard error. +This is good for debugging. + +Under the hood `nix develop -L .` will instantiate a Nix shell with everything you need. +No need to install Rust or any other dependencies like `bitcoind` or `esplora`; +and WASM toolchains are also available. +You don't even have to worry about environment variables, +since they are all set for you. + +- Checks for typos in the source code and documentation. +- Checks if all the commits are GPG-signed and follow the conventional commits style. + (again, please check [CONTRIBUTING.md](CONTRIBUTING.md)) +- Runs `cargo clippy` in all workspace. +- Runs `cargo fmt` in all workspace. +- Runs `nixpgs-fmt` in all workspace (for `.nix` files) + +You can check all the tests that our CI performs by inspecting both +the `flake.nix` and `.github/workflows/cont_integration.yml` files. + +## Developer best-practices with Nix + +We provide several development shells, +also called `devShell`s, +that assist developers with the necessary dependency and environment +to develop and test BDK. + +To access these shells, you can run: + +```shell +nix develop .#SHELL +``` + +Where `SHELL` is the name of the `devShell` you want to use. +For all the shells we provide they come with the WASM Rust target toolchain. +We provide the following shells: + +- default: latest Rust, you can omit the `#SHELL` and just run `nix develop .`. +- `msrv`: MSRV Rust version. +- `nightly`: Nightly Rust version. +- `lcov`: used in CI to generate coverage reports. + +All of these `devShell`s handle all the necessary dependencies and environment variables needed. +They also provide pre-commit git hooks covered [above](#bdks-nix-based-tests-and-ci). + +Regarding the typos check, there might be some false positives. +In that case you can add a regex rule to filter out the typos in the `.typos.toml` file. +We already included all the false positives we've found so far with some explainable comments. +Hence, you should be able to follow the examples and add your own. +Additionally, you can find more information in [`crate-ci/typos`](https://github.com/crate-ci/typos). + +As a final note on the `devShell`s, they can be conveniently automated with +[`nix-community/nix-direnv`](https://github/nix-community/nix-direnv). +`nix-direnv`, once installed, will: + +- Enable shell completion in `devShell`s. +- Seamless integrate pre-commit checks even outside a `devShell`. +- Improved caching of `devShell`s. diff --git a/README.md b/README.md index a8c18d1aa6..fb9e22647a 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ The project is split up into several crates in the `/crates` directory: - [`file_store`](./crates/file_store): A (experimental) persistence backend for storing chain data in a single file. - [`esplora`](./crates/esplora): Extends the [`esplora-client`] crate with methods to fetch chain data from an esplora HTTP server in the form that [`bdk_chain`] and `Wallet` can consume. - [`electrum`](./crates/electrum): Extends the [`electrum-client`] crate with methods to fetch chain data from an electrum server in the form that [`bdk_chain`] and `Wallet` can consume. +- [`bitcond_rpc`](./crates/bitcond_rpc) Emitting blockchain data from the `bitcoind` RPC interface. Fully working examples of how to use these components are in `/example-crates`: - [`example_cli`](./example-crates/example_cli): Library used by the `example_*` crates. Provides utilities for syncing, showing the balance, generating addresses and creating transactions without using the bdk `Wallet`. @@ -61,18 +62,19 @@ Fully working examples of how to use these components are in `/example-crates`: [`electrum-client`]: https://docs.rs/electrum-client/ [`bdk_chain`]: https://docs.rs/bdk-chain/ +## Dependencies + +- `bitcoind_rpc` depends on `bitcoind` being installed and available in `PATH` or in the `BITCOIND_EXEC` ENV variable. +- `esplora` depends on [Blockstream's version of `electrs`](https://github.com/Blockstream/electrs) + being installed and available in `PATH` or in the `ELECTRS_EXEC` ENV variable. + ## Minimum Supported Rust Version (MSRV) + This library should compile with any combination of features with Rust 1.63.0. To build with the MSRV you will need to pin dependencies as follows: ```shell -# zip 0.6.3 has MSRV 1.64.0 -cargo update -p zip --precise "0.6.2" -# time 0.3.21 has MSRV 1.65.0 -cargo update -p time --precise "0.3.20" -# jobserver 0.1.27 has MSRV 1.66.0 -cargo update -p jobserver --precise "0.1.26" # home 0.5.9 has MSRV 1.70.0 cargo update -p home --precise "0.5.5" ``` diff --git a/ci/commits_verify_signature.sh b/ci/commits_verify_signature.sh new file mode 100755 index 0000000000..5f11190a72 --- /dev/null +++ b/ci/commits_verify_signature.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Function to verify the signature of the last commit +verify_signature() { + local commit_hash + commit_hash=$(git rev-parse HEAD) + if ! git verify-commit "$commit_hash"; then + echo "Error: Last commit ($commit_hash) is not signed." + exit 1 + fi +} + +# Verify the signature of the last commit +verify_signature + +# Allow the push to proceed if the signature is valid +exit 0 diff --git a/crates/bdk/Cargo.toml b/crates/bdk/Cargo.toml index c51af75d85..1c7b37092c 100644 --- a/crates/bdk/Cargo.toml +++ b/crates/bdk/Cargo.toml @@ -13,6 +13,7 @@ edition = "2021" rust-version = "1.63" [dependencies] +log = "^0.4" rand = "^0.8" miniscript = { version = "10.0.0", features = ["serde"], default-features = false } bitcoin = { version = "0.30.0", features = ["serde", "base64", "rand-std"], default-features = false } @@ -24,8 +25,10 @@ bdk_chain = { path = "../chain", version = "0.9.0", features = ["miniscript", "s bip39 = { version = "2.0", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] +bitcoin = { version = "0.30.0", features = ["no-std"] } getrandom = "0.2" js-sys = "0.3" +miniscript = { version = "10.0.0", features = ["no-std"] } [features] default = ["std"] diff --git a/crates/bitcoind_rpc/Cargo.toml b/crates/bitcoind_rpc/Cargo.toml index 9532dd6c93..bce013a974 100644 --- a/crates/bitcoind_rpc/Cargo.toml +++ b/crates/bitcoind_rpc/Cargo.toml @@ -19,7 +19,7 @@ bitcoincore-rpc = { version = "0.17" } bdk_chain = { path = "../chain", version = "0.9", default-features = false } [dev-dependencies] -bitcoind = { version = "0.33", features = ["25_0"] } +bitcoind = "0.33" anyhow = { version = "1" } [features] diff --git a/crates/bitcoind_rpc/README.md b/crates/bitcoind_rpc/README.md index 12de87020d..0421c90ada 100644 --- a/crates/bitcoind_rpc/README.md +++ b/crates/bitcoind_rpc/README.md @@ -1,3 +1,7 @@ # BDK Bitcoind RPC This crate is used for emitting blockchain data from the `bitcoind` RPC interface. + +## Dependencies + +`bitcoind_rpc` depends on `bitcoind` being installed and available in `PATH` or in the `BITCOIND_EXEC` ENV variable. diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index 52d7093010..19bab66322 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -1,3 +1,4 @@ +use core::panic; use std::collections::{BTreeMap, BTreeSet}; use bdk_bitcoind_rpc::Emitter; @@ -25,9 +26,9 @@ struct TestEnv { impl TestEnv { fn new() -> anyhow::Result { - let daemon = match std::env::var_os("TEST_BITCOIND") { + let daemon = match std::env::var_os("BITCOIND_EXEC") { Some(bitcoind_path) => bitcoind::BitcoinD::new(bitcoind_path), - None => bitcoind::BitcoinD::from_downloaded(), + None => panic!("Cannot find bitcoind daemon, set BITCOIND_EXEC environment variable with the path to bitcoind"), }?; let client = bitcoincore_rpc::Client::new( &daemon.rpc_url(), diff --git a/crates/chain/Cargo.toml b/crates/chain/Cargo.toml index 3202188f56..e11ef0e4ea 100644 --- a/crates/chain/Cargo.toml +++ b/crates/chain/Cargo.toml @@ -18,8 +18,8 @@ bitcoin = { version = "0.30.0", default-features = false } serde_crate = { package = "serde", version = "1", optional = true, features = ["derive"] } # Use hashbrown as a feature flag to have HashSet and HashMap from it. -# note versions > 0.9.1 breaks ours 1.57.0 MSRV. -hashbrown = { version = "0.9.1", optional = true, features = ["serde"] } +# note versions 0.11.2 is compatible with MSRV of 1.63. +hashbrown = { version = "0.11.2", optional = true, features = ["serde"] } miniscript = { version = "10.0.0", optional = true, default-features = false } [dev-dependencies] diff --git a/crates/esplora/Cargo.toml b/crates/esplora/Cargo.toml index 6fbe8d5b7f..12f9aef5a0 100644 --- a/crates/esplora/Cargo.toml +++ b/crates/esplora/Cargo.toml @@ -22,7 +22,7 @@ bitcoin = { version = "0.30.0", optional = true, default-features = false } miniscript = { version = "10.0.0", optional = true, default-features = false } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] -electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } +electrsd = { version = "0.26.0", features = ["legacy"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [features] diff --git a/crates/esplora/README.md b/crates/esplora/README.md index 96d92c76c8..4c13dd00cf 100644 --- a/crates/esplora/README.md +++ b/crates/esplora/README.md @@ -3,6 +3,11 @@ BDK Esplora extends [`esplora-client`] to update [`bdk_chain`] structures from an Esplora server. +## Dependencies + +`esplora` depends on [Blockstream's version of `electrs`](https://github.com/Blockstream/electrs) +being installed and available in `PATH` or in the `ELECTRS_EXEC` ENV variable. + ## Usage There are two versions of the extension trait (blocking and async). diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index 3124bd2d11..d6f7b67976 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -1,6 +1,7 @@ use bdk_esplora::EsploraAsyncExt; use electrsd::bitcoind::bitcoincore_rpc::RpcApi; use electrsd::bitcoind::{self, anyhow, BitcoinD}; +use electrsd::electrum_client::ElectrumApi; use electrsd::{Conf, ElectrsD}; use esplora_client::{self, AsyncClient, Builder}; use std::collections::{BTreeMap, HashSet}; @@ -20,15 +21,22 @@ struct TestEnv { impl TestEnv { fn new() -> Result { let bitcoind_exe = - bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled"); - let bitcoind = BitcoinD::new(bitcoind_exe).unwrap(); + bitcoind::exe_path().expect("Cannot find bitcoind daemon, set BITCOIND_EXEC environment variable with the path to bitcoind"); + let mut bitcoind_conf = bitcoind::Conf::default(); + bitcoind_conf.p2p = bitcoind::P2P::Yes; + let bitcoind = BitcoinD::with_conf(bitcoind_exe, &bitcoind_conf)?; let mut electrs_conf = Conf::default(); electrs_conf.http_enabled = true; - let electrs_exe = - electrsd::downloaded_exe_path().expect("electrs version feature must be enabled"); + let electrs_exe = electrsd::exe_path().expect("Cannot find electrs daemon, set ELECTRS_EXEC environment variable with the path to electrs"); let electrsd = ElectrsD::with_conf(electrs_exe, &bitcoind, &electrs_conf)?; + // Alive checks + bitcoind.client.ping().unwrap(); // without using bitcoind, it is dropped and all the rest fails. + electrsd.client.ping().unwrap(); + assert!(bitcoind.client.ping().is_ok()); + assert!(electrsd.client.ping().is_ok()); + let base_url = format!("http://{}", &electrsd.esplora_url.clone().unwrap()); let client = Builder::new(base_url.as_str()).build_async()?; diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index b91231d1d1..12d1db0b3c 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -3,6 +3,7 @@ use bdk_chain::BlockId; use bdk_esplora::EsploraExt; use electrsd::bitcoind::bitcoincore_rpc::RpcApi; use electrsd::bitcoind::{self, anyhow, BitcoinD}; +use electrsd::electrum_client::ElectrumApi; use electrsd::{Conf, ElectrsD}; use esplora_client::{self, BlockingClient, Builder}; use std::collections::{BTreeMap, BTreeSet, HashSet}; @@ -36,15 +37,22 @@ struct TestEnv { impl TestEnv { fn new() -> Result { let bitcoind_exe = - bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled"); - let bitcoind = BitcoinD::new(bitcoind_exe).unwrap(); + bitcoind::exe_path().expect("Cannot find bitcoind daemon, set BITCOIND_EXEC environment variable with the path to bitcoind"); + let mut bitcoind_conf = bitcoind::Conf::default(); + bitcoind_conf.p2p = bitcoind::P2P::Yes; + let bitcoind = BitcoinD::with_conf(bitcoind_exe, &bitcoind_conf)?; let mut electrs_conf = Conf::default(); electrs_conf.http_enabled = true; - let electrs_exe = - electrsd::downloaded_exe_path().expect("electrs version feature must be enabled"); + let electrs_exe = electrsd::exe_path().expect("Cannot find electrs daemon, set ELECTRS_EXEC environment variable with the path to electrs"); let electrsd = ElectrsD::with_conf(electrs_exe, &bitcoind, &electrs_conf)?; + // Alive checks + bitcoind.client.ping().unwrap(); // without using bitcoind, it is dropped and all the rest fails. + electrsd.client.ping().unwrap(); + assert!(bitcoind.client.ping().is_ok()); + assert!(electrsd.client.ping().is_ok()); + let base_url = format!("http://{}", &electrsd.esplora_url.clone().unwrap()); let client = Builder::new(base_url.as_str()).build_blocking()?; @@ -58,8 +66,7 @@ impl TestEnv { fn reset_electrsd(mut self) -> anyhow::Result { let mut electrs_conf = Conf::default(); electrs_conf.http_enabled = true; - let electrs_exe = - electrsd::downloaded_exe_path().expect("electrs version feature must be enabled"); + let electrs_exe = electrsd::exe_path().expect("Cannot find electrs daemon, set ELECTRS_EXEC environment variable with the path to electrs"); let electrsd = ElectrsD::with_conf(electrs_exe, &self.bitcoind, &electrs_conf)?; let base_url = format!("http://{}", &electrsd.esplora_url.clone().unwrap()); diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..5973022198 --- /dev/null +++ b/flake.lock @@ -0,0 +1,244 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1706826059, + "narHash": "sha256-N69Oab+cbt3flLvYv8fYnEHlBsWwdKciNZHUbynVEOA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "25e3d4c0d3591c99929b1ec07883177f6ea70c9d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-bitcoind": { + "locked": { + "lastModified": 1697710513, + "narHash": "sha256-m5wY3DJsi6wsKdcy4k0wZwLUTNvwKIbmPAsM9SC7w5s=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "53793ca0aecf67164c630ca34dbfde552a8ab085", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "53793ca0aecf67164c630ca34dbfde552a8ab085", + "type": "github" + } + }, + "nixpkgs-kitman": { + "locked": { + "lastModified": 1677533122, + "narHash": "sha256-nYSQfuPruk5oAF0J7Pp3/Si3tS/H1lg4Rwi7QIbgDJ8=", + "owner": "jkitman", + "repo": "nixpkgs", + "rev": "61ccef8bc0a010a21ccdeb10a92220a47d8149ac", + "type": "github" + }, + "original": { + "owner": "jkitman", + "repo": "nixpkgs", + "rev": "61ccef8bc0a010a21ccdeb10a92220a47d8149ac", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1704874635, + "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1704842529, + "narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1706424699, + "narHash": "sha256-Q3RBuOpZNH2eFA1e+IHgZLAOqDD9SKhJ/sszrL8bQD4=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "7c54e08a689b53c8a1e5d70169f2ec9e2a68ffaf", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-bitcoind": "nixpkgs-bitcoind", + "nixpkgs-kitman": "nixpkgs-kitman", + "pre-commit-hooks": "pre-commit-hooks", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1707012820, + "narHash": "sha256-4cxIaHUx6/DSEVHJfK0gx4DZkJ5xHugan27KfuVPnj0=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "b83b8c3ef16d15a4ae3843d74f32dfc86caed60f", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..4564099ead --- /dev/null +++ b/flake.nix @@ -0,0 +1,211 @@ +{ + description = "BDK Flake to run all tests locally and in CI"; + + inputs = { + # stable nixpkgs (let's not YOLO on unstable) + nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + + # pin dependencies to a specific version + # find instructions here: + # + + # bitcoind pinned to 0.25.1 + nixpkgs-bitcoind.url = "github:nixos/nixpkgs?rev=53793ca0aecf67164c630ca34dbfde552a8ab085"; + # TODO: pin to 0.26.0 once it stops to fail in darwin + # pinned to 0.26.0 + # nixpkgs-bitcoind.url = "github:nixos/nixpkgs?rev=f5375ec98618347da6b036a5e06381ab7380db03"; + + # Blockstream's esplora + # inspired by fedimint CI + nixpkgs-kitman.url = "github:jkitman/nixpkgs?rev=61ccef8bc0a010a21ccdeb10a92220a47d8149ac"; + + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs = { + nixpkgs.follows = "nixpkgs"; + flake-utils.follows = "flake-utils"; + }; + }; + + flake-utils.url = "github:numtide/flake-utils"; + + pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; + }; + + outputs = { self, nixpkgs, nixpkgs-bitcoind, nixpkgs-kitman, rust-overlay, flake-utils, pre-commit-hooks, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (import rust-overlay) ]; + lib = pkgs.lib; + stdenv = pkgs.stdenv; + isDarwin = stdenv.isDarwin; + libsDarwin = with pkgs.darwin.apple_sdk.frameworks; lib.optionals isDarwin [ + # Additional darwin specific inputs can be set here + Security + SystemConfiguration + CoreServices + ]; + + # Dependencies + pkgs = import nixpkgs { + inherit system overlays; + }; + pkgs-bitcoind = import nixpkgs-bitcoind { + inherit system overlays; + }; + pkgs-kitman = import nixpkgs-kitman { + inherit system; + }; + + # Signed Commits + signed-commits = pkgs.writeShellApplication { + name = "signed-commits"; + runtimeInputs = [ pkgs.git ]; + text = builtins.readFile ./ci/commits_verify_signature.sh; + }; + + # Toolchains + # latest stable + stable = pkgs.rust-bin.stable.latest.default.override { + targets = [ "wasm32-unknown-unknown" ]; # wasm + }; + # MSRV stable + msrv = pkgs.rust-bin.stable."1.63.0".default.override { + targets = [ "wasm32-unknown-unknown" ]; # wasm + }; + # Nighly for docs + nightly = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default); + # Code coverage + coverage = pkgs.rust-bin.stable.latest.default.override { + targets = [ "wasm32-unknown-unknown" ]; # wasm + extensions = [ "llvm-tools-preview" ]; + }; + + # Common inputs + envVars = { + BITCOIND_EXEC = "${pkgs-bitcoind.bitcoind}/bin/bitcoind"; + ELECTRS_EXEC = "${pkgs-kitman.esplora}/bin/esplora"; + CC = "${stdenv.cc.nativePrefix}cc"; + AR = "${stdenv.cc.nativePrefix}ar"; + CC_wasm32_unknown_unknown = "${pkgs.llvmPackages_14.clang-unwrapped}/bin/clang-14"; + CFLAGS_wasm32_unknown_unknown = "-I ${pkgs.llvmPackages_14.libclang.lib}/lib/clang/14.0.6/include/"; + AR_wasm32_unknown_unknown = "${pkgs.llvmPackages_14.llvm}/bin/llvm-ar"; + }; + buildInputs = [ + # Add additional build inputs here + pkgs-bitcoind.bitcoind + pkgs-kitman.esplora + pkgs.openssl + pkgs.openssl.dev + pkgs.pkg-config + pkgs.curl + pkgs.libiconv + ] ++ libsDarwin; + + # WASM deps + WASMInputs = [ + # Additional wasm specific inputs can be set here + pkgs.llvmPackages_14.clang-unwrapped + pkgs.llvmPackages_14.stdenv + pkgs.llvmPackages_14.libcxxClang + pkgs.llvmPackages_14.libcxxStdenv + ]; + + nativeBuildInputs = [ + # Add additional build inputs here + pkgs.python3 + ] ++ lib.optionals isDarwin [ + # Additional darwin specific native inputs can be set here + ]; + + # Cargo update + cargoUpdate = '' + cargo update + ''; + # MSRV compat tweaks + msrvTweaks = '' + cargo update -p home --precise "0.5.5" + ''; + in + { + checks = { + # Pre-commit checks + pre-commit-check = + let + # this is a hack based on https://github.com/cachix/pre-commit-hooks.nix/issues/126 + # we want to use our own rust stuff from oxalica's overlay + _rust = pkgs.rust-bin.stable.latest.default; + rust = pkgs.buildEnv { + name = _rust.name; + inherit (_rust) meta; + buildInputs = [ pkgs.makeWrapper ]; + paths = [ _rust ]; + pathsToLink = [ "/" "/bin" ]; + postBuild = '' + for i in $out/bin/*; do + wrapProgram "$i" --prefix PATH : "$out/bin" + done + ''; + }; + in + pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + rustfmt = { + enable = true; + entry = lib.mkForce "${rust}/bin/cargo-fmt fmt --all -- --config format_code_in_doc_comments=true --check --color always"; + }; + clippy = { + enable = true; + entry = lib.mkForce "${rust}/bin/cargo-clippy clippy --all-targets --all-features -- -D warnings"; + }; + nixpkgs-fmt.enable = true; + # FIXME: uncomment and rebase after #1319 + # typos.enable = true; + commitizen.enable = true; # conventional commits + signedcommits = { + enable = true; + name = "signed-commits"; + description = "Check whether the current commit message is signed"; + stages = [ "push" ]; + entry = "${signed-commits}/bin/signed-commits"; + language = "system"; + pass_filenames = false; + }; + }; + }; + }; + + devShells = + let + # pre-commit-checks + _shellHook = (self.checks.${system}.pre-commit-check.shellHook or ""); + in + { + default = pkgs.mkShell ({ + shellHook = "${_shellHook}"; + buildInputs = buildInputs ++ WASMInputs ++ [ stable ]; + inherit nativeBuildInputs; + } // envVars // { shellHook = "${cargoUpdate} ${_shellHook}"; }); + msrv = pkgs.mkShell ({ + shellHook = "${_shellHook}"; + buildInputs = buildInputs ++ WASMInputs ++ [ msrv ]; + inherit nativeBuildInputs; + } // envVars // { shellHook = "${msrvTweaks} ${_shellHook}"; }); + nightly = pkgs.mkShell ({ + shellHook = "${_shellHook}"; + buildInputs = buildInputs ++ [ nightly ]; + inherit nativeBuildInputs; + } // envVars // { shellHook = "${cargoUpdate} ${_shellHook}"; }); + coverage = pkgs.mkShell ({ + shellHook = "${_shellHook}"; + buildInputs = buildInputs ++ [ coverage ]; + inherit nativeBuildInputs; + } // envVars // { shellHook = "${cargoUpdate} ${_shellHook}"; }); + lcov = pkgs.mkShell { + buildInputs = [ pkgs.lcov ]; + }; + }; + } + ); +}