Skip to content

Commit

Permalink
ledger: Add new macros to manipulate struct fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
ceyhunsen committed Jun 10, 2024
1 parent 726f793 commit 38433e9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 24 deletions.
20 changes: 20 additions & 0 deletions src/client/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ mod tests {
}

#[test]
#[ignore = "not implemented"]
fn generate_to_address() {
let rpc = Client::new("", bitcoincore_rpc::Auth::None).unwrap();

Expand All @@ -364,8 +365,27 @@ mod tests {
assert!(false);
};

// Generating blocks should add funds to wallet.
rpc.generate_to_address(101, &address).unwrap();

// Wallet has funds now. It should not be rejected.
// let txin = TxIn {
// previous_output: OutPoint {
// txid: rpc.ledger.get_utxos()[0],
// vout: 0,
// },
// ..Default::default()
// };
let txout = TxOut {
value: Amount::from_sat(1),
script_pubkey: address.script_pubkey(),
};
let tx = Transaction {
version: bitcoin::transaction::Version(2),
lock_time: absolute::LockTime::from_consensus(0),
input: vec![],
output: vec![txout],
};
if let Err(_) = rpc.database.lock().unwrap().verify_transaction(&tx) {
assert!(false);
};
Expand Down
60 changes: 44 additions & 16 deletions src/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,77 @@
//! This crate is designed to be used as immutable, because of the `RpcApi`'s
//! immutable nature.
use bitcoin::{Address, TxOut};
use std::cell::Cell;
use bitcoin::{Address, Transaction, TxOut};
use bitcoin_simulator::database::Database;
use std::{
cell::Cell,
sync::{Arc, Mutex},
};

mod transactions;

/// Adds a new item to a `Vec` member, guarded by a `Cell`.
#[macro_export]
macro_rules! add_item {
($member:expr, $item:expr) => {
// Update item list.
let mut items = $member.take();
items.push($item);

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

return items;
};
}

/// Mock Bitcoin ledger.
#[derive(Default)]
pub struct Ledger {
/// Private database interface. Data will be written to this temporary
/// database. Note: It is wrapped around an `Arc<Mutex<>>`. This will help
/// to use this mock in an asynchronous environment, like `async` or threads.
database: Arc<Mutex<Database>>,
/// User's addresses.
addresses: Cell<Vec<Address>>,
/// User's unspent transaction outputs.
utxos: Cell<Vec<TxOut>>,
/// User's transactions.
transactions: Cell<Vec<Transaction>>,
}

impl Ledger {
/// Creates a new empty ledger.
pub fn new() -> Self {
Self {
..Default::default()
database: Arc::new(Mutex::new(Database::connect_temporary_database().unwrap())),
addresses: Cell::new(Vec::new()),
utxos: Cell::new(Vec::new()),
transactions: Cell::new(Vec::new()),
}
}

/// Adds a new address for user.
/// Adds a new address for the user.
pub fn add_address(&self, address: Address) {
let mut addresses = self.addresses.take();
addresses.push(address);

self.addresses.set(addresses);
add_item!(self.addresses, address);
}
/// Returns address of the user.
/// Returns addresses of the user.
pub fn get_addresses(&self) -> Vec<Address> {
let addresses = self.addresses.take();
self.addresses.set(addresses.clone());

addresses
get_item!(self.addresses);
}
}

#[cfg(test)]
mod tests {
use crate::test_common;

use super::*;
use crate::test_common;

#[test]
fn new() {
Expand Down
26 changes: 18 additions & 8 deletions src/ledger/transactions.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
//! # Transaction Related Ledger Operations
use super::Ledger;
use bitcoin::TxOut;
use crate::{add_item, get_item};
use bitcoin::{Transaction, TxOut};

impl Ledger {
/// Adds a new UTXO to user's UTXO's.
pub fn add_utxo(&self, utxo: TxOut) {
let mut utxos = self.utxos.take();
utxos.push(utxo);

self.utxos.set(utxos);
add_item!(self.utxos, utxo);
}
/// Returns UTXO's of the user.
pub fn get_utxos(&self) -> Vec<TxOut> {
let utxos = self.utxos.take();
self.utxos.set(utxos.clone());
get_item!(self.utxos);
}

utxos
/// Adds transaction to current block, without checking anything.
pub fn add_transaction_unconditionally(&self, transaction: Transaction) {
self.database
.lock()
.unwrap()
.insert_transaction_unconditionally(&transaction)
.unwrap();

add_item!(self.transactions, transaction);
}
/// Returns user's list of transactions.
pub fn get_transactions(&self) -> Vec<Transaction> {
get_item!(self.transactions);
}
}

Expand Down

0 comments on commit 38433e9

Please sign in to comment.