Skip to content

Commit

Permalink
Merge pull request #3 from chainwayxyz/async-support
Browse files Browse the repository at this point in the history
Async support
  • Loading branch information
ceyhunsen authored Jun 27, 2024
2 parents 84587f7 + bc22f84 commit 3dfe1e9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 27 deletions.
24 changes: 18 additions & 6 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,39 @@
//! Client crate mocks the `Client` struct in `bitcoincore-rpc`.
use crate::ledger::Ledger;
use bitcoincore_rpc::{Auth, RpcApi};

mod rpc_api;

/// This trait defines non-functional interfaces for RPC interfaces, like
/// `new()`. This is needed if target application wants to choose actual rpc and
/// this via trait definitions. This is helpful for choosing different rpc
/// interface between test and release builds.
pub trait RpcApiWrapper: RpcApi + std::marker::Sync + std::marker::Send + 'static {
fn new(url: &str, auth: Auth) -> bitcoincore_rpc::Result<Self>;
}

/// Compatibility implementation for `bitcoincore_rpc::Client`.
impl RpcApiWrapper for bitcoincore_rpc::Client {
fn new(url: &str, auth: Auth) -> bitcoincore_rpc::Result<Self> {
bitcoincore_rpc::Client::new(url, auth)
}
}

/// Mock Bitcoin RPC client.
pub struct Client {
/// Bitcoin ledger.
ledger: Ledger,
}

impl Client {
impl RpcApiWrapper for Client {
/// Creates a new mock Client interface.
///
/// # Parameters
///
/// Parameters are just here to match `bitcoincore_rpc::Client::new()`. They
/// are not used and can be dummy values.
///
/// # Panics
///
/// This function can panic if `Ledger` can't be created.
pub fn new(_url: &str, _auth: bitcoincore_rpc::Auth) -> bitcoincore_rpc::Result<Self> {
fn new(_url: &str, _auth: bitcoincore_rpc::Auth) -> bitcoincore_rpc::Result<Self> {
Ok(Self {
ledger: Ledger::new(),
})
Expand Down
1 change: 1 addition & 0 deletions src/client/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ impl RpcApi for Client {
#[cfg(test)]
mod tests {
use super::*;
use crate::RpcApiWrapper;
use bitcoin::{Amount, Network};

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/ledger/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ mod tests {
fn addresses() {
let ledger = Ledger::new();

assert_eq!(ledger.credentials.take().len(), 0);
assert_eq!(ledger.credentials.lock().unwrap().take().len(), 0);

let credential = Ledger::generate_credential();
ledger.add_credential(credential.clone());

let credentials = ledger.credentials.take();
let credentials = ledger.credentials.lock().unwrap().take();
assert_eq!(credentials.len(), 1);

assert_eq!(credential, credentials.get(0).unwrap().to_owned());
Expand Down
27 changes: 15 additions & 12 deletions src/ledger/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,33 @@
macro_rules! add_item_to_vec {
($member:expr, $item:expr) => {
// Update item list.
let mut items = $member.take();
let mut items = $member.lock().unwrap().take();
items.push($item);

// Commit new change.
$member.set(items);
$member.lock().unwrap().set(items);
};
}
/// Removes given item from a `Vec` member, which is guarded by a `Cell`.
#[macro_export]
macro_rules! remove_item_from_vec {
($member:expr, $item:expr) => {
// Get item list.
let mut items = $member.take();
let mut items = $member.lock().unwrap().take();

// Delete given item.
items.retain(|&i| i != $item);

// Commit new change.
$member.set(items);
$member.lock().unwrap().set(items);
};
}
/// Returns items of a `Vec` member, which is guarded by a `Cell`.
#[macro_export]
macro_rules! return_vec_item {
($member:expr) => {
let items = $member.take();
$member.set(items.clone());
let items = $member.lock().unwrap().take();
$member.lock().unwrap().set(items.clone());

return items;
};
Expand All @@ -43,28 +43,31 @@ macro_rules! return_vec_item {
#[macro_export]
macro_rules! update_item {
($member:expr, $item:expr) => {
$member.set($item);
$member.lock().unwrap().set($item);
};
}

/// Assigns an item from member to given assignee, which is guarded by a `Cell`.
#[macro_export]
macro_rules! get_item {
($member:expr, $assignee:ident) => {
let $assignee = $member.take();
$member.set($assignee.clone());
let $assignee = $member.lock().unwrap().take();
$member.lock().unwrap().set($assignee.clone());
};
}

#[cfg(test)]
mod tests {
use std::cell::Cell;
use std::{
cell::Cell,
sync::{Arc, Mutex},
};

/// Temporary struct for macro testing.
#[derive(Default)]
struct Test {
pub vec_member_1: Cell<Vec<isize>>,
pub int_member_1: Cell<isize>,
pub vec_member_1: Arc<Mutex<Cell<Vec<isize>>>>,
pub int_member_1: Arc<Mutex<Cell<isize>>>,
}

#[test]
Expand Down
17 changes: 10 additions & 7 deletions src/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
use address::UserCredential;
use bitcoin::{OutPoint, Transaction};
use std::cell::Cell;
use std::{
cell::Cell,
sync::{Arc, Mutex},
};

mod address;
mod errors;
Expand All @@ -19,20 +22,20 @@ mod utxo;
/// Mock Bitcoin ledger.
pub struct Ledger {
/// User's keys and address.
credentials: Cell<Vec<UserCredential>>,
credentials: Arc<Mutex<Cell<Vec<UserCredential>>>>,
/// Happened transactions.
transactions: Cell<Vec<Transaction>>,
transactions: Arc<Mutex<Cell<Vec<Transaction>>>>,
/// Unspent transaction outputs.
utxos: Cell<Vec<OutPoint>>,
utxos: Arc<Mutex<Cell<Vec<OutPoint>>>>,
}

impl Ledger {
/// Creates a new empty ledger.
pub fn new() -> Self {
Self {
credentials: Cell::new(Vec::new()),
utxos: Cell::new(Vec::new()),
transactions: Cell::new(Vec::new()),
credentials: Arc::new(Mutex::new(Cell::new(Vec::new()))),
utxos: Arc::new(Mutex::new(Cell::new(Vec::new()))),
transactions: Arc::new(Mutex::new(Cell::new(Vec::new()))),
}
}
}
Expand Down

0 comments on commit 3dfe1e9

Please sign in to comment.