Skip to content

fixup/ci: audit and machete #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 45 additions & 127 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ env:
CARGO_TERM_COLOR: auto
PGPASSWORD: password
DATABASE_TEST_URL: postgres://postgres:password@localhost:5432/testdb

DATABASE_URL: postgres://postgres:password@localhost:5432/testdb
jobs:
wallet-is-persisted:
name: Test wallet persistence
all-tests:
name: Run all wallet tests
runs-on: ubuntu-latest
services:
postgres:
Expand All @@ -35,141 +35,59 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Create database

- name: Install dependencies
run: |
sudo apt-get install libpq-dev -y
psql -h localhost -p 5432 -U postgres -d postgres -c 'create user testuser'
psql -h localhost -p 5432 -U postgres -d postgres -c 'create database testdb with owner = testuser'
- name: Test wallet_is_persisted
run: cargo test wallet_is_persisted -- --show-output
# Install sqlx-cli
cargo install sqlx-cli --no-default-features --features native-tls,postgres

test-three-wallets:
name: Test three wallets list transactions
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Create database
- name: Create and prepare database
run: |
sudo apt-get install libpq-dev -y
psql -h localhost -p 5432 -U postgres -d postgres -c 'create user testuser'
psql -h localhost -p 5432 -U postgres -d postgres -c 'create database testdb with owner = testuser'
- name: Test test_three_wallets_list_transactions
run: cargo test test_three_wallets_list_transactions -- --show-output

wallet-load-checks:
name: Test wallet load checks
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Create database
- name: Run all wallet tests
run: |
sudo apt-get install libpq-dev -y
psql -h localhost -p 5432 -U postgres -d postgres -c 'create user testuser'
psql -h localhost -p 5432 -U postgres -d postgres -c 'create database testdb with owner = testuser'
- name: Test wallet_load_checks
run: cargo test wallet_load_checks -- --show-output
# Test 1: wallet_is_persisted
sqlx migrate run --source migrations/postgres
cargo test wallet_is_persisted -- --show-output
sqlx migrate revert --all

# Test 2: test_three_wallets_list_transactions
sqlx migrate run --source migrations/postgres
cargo test test_three_wallets_list_transactions -- --show-output
sqlx migrate revert --all

# Test 3: wallet_load_checks
sqlx migrate run --source migrations/postgres
cargo test wallet_load_checks -- --show-output
sqlx migrate revert --all

# Test 4: single_descriptor_wallet_persist_and_recover
sqlx migrate run --source migrations/postgres
cargo test single_descriptor_wallet_persist_and_recover -- --show-output
sqlx migrate revert --all

# Test 5: two_wallets_load
sqlx migrate run --source migrations/postgres
cargo test two_wallets_load -- --show-output
sqlx migrate revert --all

single-descriptor-wallet:
name: Test single descriptor wallet
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Create database
- name: Check fmt and run clippy
run: |
sudo apt-get install libpq-dev -y
psql -h localhost -p 5432 -U postgres -d postgres -c 'create user testuser'
psql -h localhost -p 5432 -U postgres -d postgres -c 'create database testdb with owner = testuser'
- name: Test single_descriptor_wallet_persist_and_recover
run: cargo test single_descriptor_wallet_persist_and_recover -- --show-output
cargo fmt --all -- --check
cargo clippy --all-targets -- -Dwarnings

two-wallets-load:
name: Test two wallets load
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Create database
- name: Security Audit
run: |
sudo apt-get install libpq-dev -y
psql -h localhost -p 5432 -U postgres -d postgres -c 'create user testuser'
psql -h localhost -p 5432 -U postgres -d postgres -c 'create database testdb with owner = testuser'
- name: Test two_wallets_load
run: cargo test two_wallets_load -- --show-output
cargo install cargo-audit
cargo audit

fmt-clippy:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Check fmt
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets -- -Dwarnings
- name: Check Unused Dependencies
run: |
cargo install cargo-machete
cargo machete
11 changes: 5 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ edition = "2021"
bdk_wallet = { version = "1.2.0", features = ["test-utils"] }
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"
sqlx = { version = "0.8.1", default-features = false, features = ["runtime-tokio", "tls-rustls-ring","derive", "postgres", "sqlite", "json", "chrono", "uuid", "sqlx-macros", "migrate"] }
thiserror = "1"
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] }
sqlx = { version = "0.8.5", default-features = false, features = ["runtime-tokio","migrate", "tls-rustls-ring", "derive", "postgres", "sqlite", "json", "chrono", "uuid"] }
thiserror = "2"
tokio = { version = "1.44.0", features = ["macros", "rt-multi-thread"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde_json", "json"] }
sqlx-postgres-tester = "0.1.1"

[dev-dependencies]
assert_matches = "1.5.0"
anyhow = "1.0.89"
bdk_electrum = { version = "0.20.1"}
anyhow = "1.0.98"
bdk_electrum = { version = "0.21.0"}
rustls = "0.23.14"

[[example]]
Expand Down
25 changes: 25 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# PostgreSQL commands
start-postgres:
docker run -d --name postgres \
-p 5432:5432 \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=mydatabase \
postgres:15

test-postgres:
PGPASSWORD=password psql -h localhost -p 5432 -U postgres -d mydatabase -c "SELECT 1"

stop-postgres:
docker stop postgres && docker rm postgres

# DATABASE_URL: postgres://postgres:password@localhost:5432/mydatabase
example:
cargo run --example bdk_sqlx_postgres

# Database migration
run-migrations:
sqlx migrate run --source migrations/postgres

undo-migrations:
sqlx migrate revert --all
2 changes: 2 additions & 0 deletions audit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[advisories]
ignore = ["RUSTSEC-2023-0071"]
12 changes: 6 additions & 6 deletions examples/bdk_sqlx_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ use std::collections::HashSet;
use std::io::Write;

use bdk_electrum::{electrum_client, BdkElectrumClient};
use bdk_sqlx::pg_store_builder::PgStoreBuilder;
use bdk_sqlx::sqlx::Postgres;
use bdk_sqlx::{PgStoreBuilder, Store};
use bdk_sqlx::Store;
use bdk_wallet::bitcoin::secp256k1::Secp256k1;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::{KeychainKind, PersistedWallet, Wallet};
use rustls::crypto::ring::default_provider;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;

// Create and persist a BDK wallet to postgres.

// wallet 1
Expand Down Expand Up @@ -59,8 +59,8 @@ async fn main() -> anyhow::Result<()> {

let mut store = PgStoreBuilder::new(wallet_name.clone())
.network(NETWORK)
.migrate(true)
.build_with_url(&url)
.url(&url)
.build()
.await?;

let mut wallet = match Wallet::load().load_wallet_async(&mut store).await? {
Expand Down Expand Up @@ -90,8 +90,8 @@ async fn main() -> anyhow::Result<()> {

let mut store = PgStoreBuilder::new(wallet_name.clone())
.network(NETWORK)
.migrate(true)
.build_with_url(&url)
.url(&url)
.build()
.await?;

let mut wallet = match Wallet::load().load_wallet_async(&mut store).await? {
Expand Down
60 changes: 44 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,57 @@
mod postgres;
mod sqlite;

/// Builder for Store
pub mod pg_store_builder;
#[cfg(test)]
mod test;

use std::future::Future;
use std::pin::Pin;

use bdk_wallet::bitcoin;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::chain::miniscript;
pub use sqlx;
use sqlx::Database;
use sqlx::Pool;
use sqlx::{Database, PgPool};
use std::future::Future;
use std::pin::Pin;
use std::sync::OnceLock;
use tracing::warn;

/// Result type for bdk-sqlx
pub type Result<T> = core::result::Result<T, BdkSqlxError>;

/// Thread-safe storage for the network configuration that's shared across all Store instances.
/// This ensures consistent network validation across multiple threads.
static NETWORK: OnceLock<Network> = OnceLock::new();

/// Retrieves the current global network configuration for validation operations.
///
/// Returns the current network configuration or an error if not initialized.
fn get_network() -> Result<Network> {
NETWORK
.get()
.copied()
.ok_or_else(|| BdkSqlxError::GetNetworkFailure)
}

/// Sets the global network configuration to ensure consistent validation across threads.
///
/// Returns an error if the network is already initialized with a different network.
fn initialize_network(network: Network) -> Result<()> {
match NETWORK.get() {
Some(current) if *current == network => {
warn!("initialize_network called more than once");
Ok(())
}
Some(current) => Err(BdkSqlxError::DuplicateInitNetwork {
current: *current,
network,
}),
None => NETWORK
.set(network)
.map_err(BdkSqlxError::SetNetworkFailure),
}
}

/// Crate error
#[derive(Debug, thiserror::Error)]
Expand All @@ -33,9 +72,6 @@ pub enum BdkSqlxError {
/// sqlx error
#[error("sqlx error: {0}")]
Sqlx(#[from] sqlx::Error),
/// migrate error
#[error("migrate error: {0}")]
Migrate(#[from] sqlx::migrate::MigrateError),
/// Network confusion
#[error("Invalid Network expected {expected}, got {got}")]
InvalidNetwork {
Expand Down Expand Up @@ -84,12 +120,4 @@ pub struct Store<DB: Database> {
wallet_name: String,
}

/// Build a new instance of the PgStoreBuilder
pub struct PgStoreBuilder {
wallet_name: String,
pool: Option<PgPool>,
migrate: bool,
network: Option<Network>,
}

type FutureResult<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>>;
type FutureResult<'a, T, E> = Pin<Box<dyn Future<Output = std::result::Result<T, E>> + Send + 'a>>;
Loading
Loading