From fcf23b1808209221a878fafc7406cfaa6428fb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 11:50:25 +0300 Subject: [PATCH 01/10] logging: Small improvements. --- src/ledger/block.rs | 2 +- src/rpc/mod.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ledger/block.rs b/src/ledger/block.rs index d885a15..bfb565a 100644 --- a/src/ledger/block.rs +++ b/src/ledger/block.rs @@ -21,7 +21,7 @@ impl Ledger { /// # Panics /// /// Will panic if there was a problem writing data to ledger. - #[tracing::instrument] + #[tracing::instrument(skip(self))] pub fn mine_block(&self, address: &Address) -> Result { let mut transactions = self.get_mempool_transactions(); let coinbase_transaction = self.create_coinbase_transaction( diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 5b27f5c..9b08051 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -60,6 +60,8 @@ pub fn spawn_rpc_server( None => TcpListener::bind((host, 0))?.local_addr()?.to_string(), }; + tracing::trace!("Starting a new RPC server at {url}"); + Ok(start_server_thread(url)) } From d966d87736309619278a6c66bd8291c25436ea93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 11:50:50 +0300 Subject: [PATCH 02/10] rpc: adapter: Return type updates. --- src/rpc/adapter/wallet.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/rpc/adapter/wallet.rs b/src/rpc/adapter/wallet.rs index af14584..86731d7 100644 --- a/src/rpc/adapter/wallet.rs +++ b/src/rpc/adapter/wallet.rs @@ -2,7 +2,10 @@ use crate::Client; use bitcoin::{Address, Amount, Txid}; -use bitcoincore_rpc::{json, Error, RpcApi}; +use bitcoincore_rpc::{ + json::{self, GetTransactionResult}, + Error, RpcApi, +}; use std::str::FromStr; pub fn getnewaddress( @@ -25,12 +28,12 @@ pub fn gettransaction( txid: String, include_watchonly: Option, _verbose: Option, -) -> Result { +) -> Result { let txid = Txid::from_str(&txid).unwrap(); let tx = client.get_transaction(&txid, include_watchonly)?; - Ok(serde_json::to_string_pretty(&tx)?) + Ok(tx) } // This has nothing to do with us. Ignore it. @@ -46,7 +49,7 @@ pub fn sendtoaddress( conf_target: Option, _estimate_mode: Option<&str>, _avoid_reuse: Option, -) -> Result { +) -> Result { let address = match Address::from_str(&address) { Ok(a) => a, Err(e) => { @@ -72,7 +75,7 @@ pub fn sendtoaddress( None, )?; - Ok(txid.to_string()) + Ok(txid) } #[cfg(test)] From 472d5dc0b0f9c751a3e12c4e2b83b0ae0cb2b3ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 11:51:14 +0300 Subject: [PATCH 03/10] rpc: get_raw_tx: Initial impl for 2 return types. --- src/rpc/adapter/rawtransactions.rs | 116 ++++++++++++++++++++++++++--- src/rpc/traits.rs | 17 +++-- 2 files changed, 116 insertions(+), 17 deletions(-) diff --git a/src/rpc/adapter/rawtransactions.rs b/src/rpc/adapter/rawtransactions.rs index c8d6007..397b2d9 100644 --- a/src/rpc/adapter/rawtransactions.rs +++ b/src/rpc/adapter/rawtransactions.rs @@ -2,28 +2,88 @@ use crate::utils::encode_to_hex; use crate::Client; -use bitcoin::{consensus::encode::deserialize_hex, BlockHash, Transaction, Txid}; +use bitcoin::{consensus::encode::deserialize_hex, hex::DisplayHex, BlockHash, Transaction, Txid}; use bitcoincore_rpc::{Error, RpcApi}; +use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; use std::str::FromStr; +#[derive(Clone, PartialEq, Eq, Debug, Deserialize)] +pub enum GetrawtransactionReturn { + NoneVerbose(String), + Verbose(Box), +} +impl Serialize for GetrawtransactionReturn { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + GetrawtransactionReturn::NoneVerbose(stri) => serializer.serialize_str(stri), + GetrawtransactionReturn::Verbose(strct) => { + let mut state = serializer.serialize_struct("GetRawTransactionResult", 14)?; + + if strct.in_active_chain.is_some() { + state.serialize_field("in_active_chain", &strct.in_active_chain)?; + } + state + .serialize_field("hex", &strct.hex.to_hex_string(bitcoin::hex::Case::Lower))?; + state.serialize_field("txid", &strct.txid)?; + state.serialize_field("hash", &strct.hash)?; + state.serialize_field("size", &strct.size)?; + state.serialize_field("vsize", &strct.vsize)?; + state.serialize_field("version", &strct.version)?; + state.serialize_field("locktime", &strct.locktime)?; + + #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] + struct Vin { + sequence: u32, + } + let vins: Vec = strct + .vin + .iter() + .map(|vin| Vin { + sequence: vin.sequence, + }) + .collect(); + state.serialize_field("vin", &vins)?; + + state.serialize_field("vout", &strct.vout)?; + if strct.blockhash.is_some() { + state.serialize_field("blockhash", &strct.blockhash)?; + } + if strct.confirmations.is_some() { + state.serialize_field("confirmations", &strct.confirmations)?; + } + if strct.time.is_some() { + state.serialize_field("time", &strct.time)?; + } + if strct.blocktime.is_some() { + state.serialize_field("blocktime", &strct.blocktime)?; + } + state.end() + } + } + } +} pub fn getrawtransaction( client: &Client, txid: String, verbose: Option, blockhash: Option, -) -> Result { +) -> Result { let txid = Txid::from_str(&txid).unwrap(); - let res: String = match verbose { + let res: GetrawtransactionReturn = match verbose { None | Some(false) => { let tx = client.get_raw_transaction(&txid, blockhash.as_ref())?; - encode_to_hex(&tx) + GetrawtransactionReturn::NoneVerbose(encode_to_hex(&tx)) } Some(true) => { - let tx = client.get_raw_transaction_info(&txid, blockhash.as_ref())?; + let tx: bitcoincore_rpc::json::GetRawTransactionResult = + client.get_raw_transaction_info(&txid, blockhash.as_ref())?; - serde_json::to_string_pretty(&tx).unwrap() + GetrawtransactionReturn::Verbose(Box::new(tx)) } }; @@ -67,11 +127,13 @@ pub fn signrawtransactionwithwallet( mod tests { use crate::{ ledger, + rpc::adapter::GetrawtransactionReturn, utils::{decode_from_hex, encode_to_hex}, Client, RpcApiWrapper, }; use bitcoin::{ - absolute::LockTime, transaction::Version, Amount, OutPoint, Transaction, TxIn, TxOut, Txid, + absolute::LockTime, consensus::Decodable, transaction::Version, Amount, OutPoint, + Transaction, TxIn, TxOut, Txid, }; use bitcoincore_rpc::RpcApi; @@ -96,9 +158,45 @@ mod tests { let tx = client.get_raw_transaction(&txid, None).unwrap(); let encoded_tx = super::getrawtransaction(&client, txid.to_string(), None, None).unwrap(); - let encoded_tx = decode_from_hex(encoded_tx).unwrap(); - assert_eq!(tx, encoded_tx); + if let GetrawtransactionReturn::NoneVerbose(encoded_tx) = encoded_tx { + assert_eq!(tx, decode_from_hex(encoded_tx).unwrap()); + } else { + panic!(""); + } + } + + #[test] + fn getrawtransactionverbose() { + let client = Client::new("getrawtransaction", bitcoincore_rpc::Auth::None).unwrap(); + + let address = client.get_new_address(None, None).unwrap().assume_checked(); + let txid = client + .send_to_address( + &address, + Amount::from_sat(0x45), + None, + None, + None, + None, + None, + None, + ) + .unwrap(); + + let tx = client.get_raw_transaction(&txid, None).unwrap(); + + let encoded_tx = + super::getrawtransaction(&client, txid.to_string(), Some(true), None).unwrap(); + + if let GetrawtransactionReturn::Verbose(encoded_tx) = encoded_tx { + assert_eq!( + tx, + Transaction::consensus_decode(&mut encoded_tx.hex.as_slice()).unwrap() + ); + } else { + panic!("Should be verbose variant"); + } } #[test] diff --git a/src/rpc/traits.rs b/src/rpc/traits.rs index 7080ebe..d20c2e7 100644 --- a/src/rpc/traits.rs +++ b/src/rpc/traits.rs @@ -3,9 +3,10 @@ //! This crate implements [`jsonrpsee`] traits, using [`adapter`] functions. //! This is the entry point for the RPC calls. -use super::adapter; +use super::adapter::{self, GetrawtransactionReturn}; use crate::Client; -use bitcoin::BlockHash; +use bitcoin::{BlockHash, Txid}; +use bitcoincore_rpc::json::GetTransactionResult; use jsonrpsee::core::async_trait; use jsonrpsee::proc_macros::rpc; use jsonrpsee::types::ErrorObjectOwned; @@ -57,7 +58,7 @@ pub trait Rpc { txid: String, verbose: Option, blockhash: Option, - ) -> Result; + ) -> Result; #[method(name = "sendrawtransaction")] async fn sendrawtransaction( @@ -79,7 +80,7 @@ pub trait Rpc { txid: String, include_watchonly: Option, verbose: Option, - ) -> Result; + ) -> Result; #[method(name = "sendtoaddress")] async fn sendtoaddress( @@ -93,7 +94,7 @@ pub trait Rpc { conf_target: Option, estimate_mode: Option<&str>, avoid_reuse: Option, - ) -> Result; + ) -> Result; #[method(name = "fundrawtransaction")] async fn fundrawtransaction( @@ -165,7 +166,7 @@ impl RpcServer for Client { txid: String, verbose: Option, blockhash: Option, - ) -> Result { + ) -> Result { to_jsonrpsee_error(adapter::getrawtransaction(self, txid, verbose, blockhash)) } @@ -190,7 +191,7 @@ impl RpcServer for Client { txid: String, include_watchonly: Option, verbose: Option, - ) -> Result { + ) -> Result { to_jsonrpsee_error(adapter::gettransaction( self, txid, @@ -210,7 +211,7 @@ impl RpcServer for Client { conf_target: Option, estimate_mode: Option<&str>, avoid_reuse: Option, - ) -> Result { + ) -> Result { to_jsonrpsee_error(adapter::sendtoaddress( self, address, From 12fec6dbec99b6c3c36164adc2b7c7558e07c3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 14:29:57 +0300 Subject: [PATCH 04/10] rpc: Disable RPC interface. --- Cargo.toml | 5 +- src/bin/bitcoin_mock_rpc.rs | 61 ------------- src/client/rpc_api.rs | 4 +- src/lib.rs | 4 +- src/utils.rs | 8 +- tests/rpc.rs | 173 ------------------------------------ 6 files changed, 12 insertions(+), 243 deletions(-) delete mode 100644 src/bin/bitcoin_mock_rpc.rs delete mode 100644 tests/rpc.rs diff --git a/Cargo.toml b/Cargo.toml index bfc5554..1b6cde3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,5 +20,6 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tower = "0.4.13" clap = { version = "4.5.16", features = ["derive"] } -[[bin]] -name = "bitcoin_mock_rpc" +[features] +# Enables RPC server interface. Note: Not stable nor complete. Use it in your own caution. +rpc_server = [] diff --git a/src/bin/bitcoin_mock_rpc.rs b/src/bin/bitcoin_mock_rpc.rs deleted file mode 100644 index 6d8cd3e..0000000 --- a/src/bin/bitcoin_mock_rpc.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! # RPC Server Starter -//! -//! This binary can start an RPC server for listening RPC calls. Can be spawned -//! multiple times. Each server will have an independent blockchain. - -use bitcoin_mock_rpc::rpc::spawn_rpc_server; -use clap::Parser; -use std::process::exit; -use tracing::level_filters::LevelFilter; -use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; - -/// Bitcoin Mock Rpc (C) Chainway, 2024 -#[derive(Parser, Debug)] -#[command(version, about, long_about = None)] -struct Args { - /// Verbosity level, ranging from 0 (none) to 5 (highest) - #[arg(short, long, default_value_t = 0)] - verbose: u8, - /// Optional host address - #[arg(default_value_t = String::from("127.0.0.1"))] - pub host: String, - /// Optional host port (if not given, requests a random port from OS) - #[arg(default_value_t = 0)] - pub port: u16, -} - -/// Initializes tracing. -fn initialize_logger(level: u8) { - let level = match level { - 0 => return, // No tracing output - 1 => LevelFilter::ERROR, - 2 => LevelFilter::WARN, - 3 => LevelFilter::INFO, - 4 => LevelFilter::DEBUG, - 5 => LevelFilter::TRACE, - _ => { - eprintln!("Verbosity level can only be between 0 and 5 (given {level})!"); - exit(1); - } - }; - - let layer = fmt::layer().with_test_writer(); - let filter = EnvFilter::builder() - .with_default_directive(level.into()) - .from_env_lossy(); - - tracing_subscriber::registry() - .with(layer) - .with(filter) - .init(); -} - -fn main() { - let args = Args::parse(); - initialize_logger(args.verbose); - - let server = spawn_rpc_server(Some(&args.host), Some(args.port)).unwrap(); - println!("Server started at {}", server.0); - - server.1.join().unwrap() -} diff --git a/src/client/rpc_api.rs b/src/client/rpc_api.rs index f487eac..4b533cf 100644 --- a/src/client/rpc_api.rs +++ b/src/client/rpc_api.rs @@ -613,7 +613,7 @@ impl RpcApi for Client { #[cfg(test)] mod tests { - use crate::{ledger::Ledger, utils::decode_from_hex, Client, RpcApiWrapper}; + use crate::{ledger::Ledger, utils::_decode_from_hex, Client, RpcApiWrapper}; use bitcoin::{ consensus::{deserialize, Decodable}, Amount, Network, OutPoint, Transaction, TxIn, @@ -936,7 +936,7 @@ mod tests { let res = rpc.fund_raw_transaction(&tx, None, None).unwrap(); let new_tx = String::consensus_decode(&mut res.hex.as_slice()).unwrap(); - let new_tx = decode_from_hex::(new_tx).unwrap(); + let new_tx = _decode_from_hex::(new_tx).unwrap(); assert_eq!(tx, new_tx); assert_eq!(res.change_position, -1); diff --git a/src/lib.rs b/src/lib.rs index 62a0930..12cef37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,10 @@ pub mod client; mod ledger; -pub mod rpc; mod utils; // Re-imports. pub use client::*; + +#[cfg(feature = "rpc_server")] +pub mod rpc; diff --git a/src/utils.rs b/src/utils.rs index 54de117..d41958b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -128,7 +128,7 @@ where } /// Decodes given hex string to a Rust struct. -pub fn decode_from_hex(hex: String) -> Result +pub fn _decode_from_hex(hex: String) -> Result where T: bitcoin::consensus::Decodable, { @@ -164,7 +164,7 @@ pub fn initialize_logger() -> Result<(), tracing_subscriber::util::TryInitError> #[cfg(test)] mod tests { - use super::{decode_from_hex, encode_to_hex}; + use super::{_decode_from_hex, encode_to_hex}; use bitcoin::{ absolute::Height, hashes::sha256d::Hash, transaction::Version, Address, Amount, OutPoint, Transaction, TxIn, TxMerkleNode, TxOut, Txid, @@ -249,7 +249,7 @@ mod tests { ); let encoded_txid = encode_to_hex(&txid); - let decoded_txid = decode_from_hex::(encoded_txid).unwrap(); + let decoded_txid = _decode_from_hex::(encoded_txid).unwrap(); assert_eq!(txid, decoded_txid); } @@ -280,7 +280,7 @@ mod tests { }; let encoded_tx = encode_to_hex(&tx); - let decoded_tx = decode_from_hex::(encoded_tx).unwrap(); + let decoded_tx = _decode_from_hex::(encoded_tx).unwrap(); assert_eq!(tx, decoded_tx); } diff --git a/tests/rpc.rs b/tests/rpc.rs deleted file mode 100644 index f88cc15..0000000 --- a/tests/rpc.rs +++ /dev/null @@ -1,173 +0,0 @@ -//! # RPC Interface Tests -//! -//! These tests aims to show RPC server can get up and handle requests in -//! different conditions, like single or multi-threaded environments. Therefore -//! correctness of the call results aren't necessarily important for these test. -//! It is the job of other tests. - -use bitcoin::absolute::Height; -use bitcoin::consensus::deserialize; -use bitcoin::transaction::Version; -use bitcoin::{Amount, OutPoint, Transaction, TxIn, TxOut}; -use bitcoin_mock_rpc::rpc::spawn_rpc_server; -use bitcoincore_rpc::RpcApi; -use jsonrpsee::core::client::ClientT; -use jsonrpsee::{http_client::HttpClient, rpc_params}; - -mod common; - -#[tokio::test] -async fn check_server_availability() { - let server = spawn_rpc_server(None, None).unwrap(); - let url = format!("http://{}", server.0); - println!("Server URL: {url}"); - - let client = HttpClient::builder().build(url).unwrap(); - let params = rpc_params![]; - - let response: String = client.request("getnewaddress", params).await.unwrap(); - println!("Server response: {:?}", response); -} - -#[test] -fn create_connection() { - let server = spawn_rpc_server(None, None).unwrap(); - let url = server.0.to_string(); - println!("Server started at {url}"); - - let _should_not_panic = - bitcoincore_rpc::Client::new(url.as_str(), bitcoincore_rpc::Auth::None).unwrap(); -} - -#[test] -fn address_related_rpc_calls() { - let server = spawn_rpc_server(None, None).unwrap(); - let url = server.0.to_string(); - println!("Server started at {url}"); - - let rpc = bitcoincore_rpc::Client::new(url.as_str(), bitcoincore_rpc::Auth::None).unwrap(); - - let address = rpc.get_new_address(None, None).unwrap(); - println!("New address: {address:?}"); -} - -#[test] -fn block_related_rpc_calls() { - let server = spawn_rpc_server(None, None).unwrap(); - let url = server.0.to_string(); - println!("Server started at {url}"); - - let rpc = bitcoincore_rpc::Client::new(url.as_str(), bitcoincore_rpc::Auth::None).unwrap(); - - // Generate some blocks. - let address = rpc.get_new_address(None, None).unwrap(); - rpc.generate_to_address(101, &address.assume_checked()) - .unwrap(); - - let height = rpc.get_block_count().unwrap(); - assert_eq!(height, 101); - - let tip_hash = rpc.get_best_block_hash().unwrap(); - - let block = rpc.get_block(&tip_hash).unwrap(); - let header = rpc.get_block_header(&tip_hash).unwrap(); - assert_eq!(block.header, header); - - let txout = rpc - .get_tx_out(&block.txdata.first().unwrap().compute_txid(), 0, None) - .unwrap() - .unwrap(); - assert_eq!(txout.confirmations, 1); -} - -#[test] -fn transaction_related_rpc_calls() { - let server = spawn_rpc_server(None, None).unwrap(); - let url = server.0.to_string(); - println!("Server started at {url}"); - - let rpc = bitcoincore_rpc::Client::new(url.as_str(), bitcoincore_rpc::Auth::None).unwrap(); - - let witness = common::create_witness(); - let address = common::create_address_from_witness(witness.0); - - let txid = rpc - .send_to_address( - &address, - Amount::from_sat(0x45 * 0x45), - None, - None, - None, - None, - None, - None, - ) - .unwrap(); - - let _tx = rpc.get_raw_transaction(&txid, None).unwrap(); - - let txin = TxIn { - previous_output: OutPoint { txid, vout: 0 }, - witness: witness.1, - ..Default::default() - }; - let txout = TxOut { - value: Amount::from_sat(0x45), - script_pubkey: address.script_pubkey(), - }; - let tx = Transaction { - input: vec![txin], - output: vec![txout], - version: Version::TWO, - lock_time: bitcoin::absolute::LockTime::Blocks(Height::ZERO), - }; - - let new_txid = rpc.send_raw_transaction(&tx).unwrap(); - assert_ne!(txid, new_txid); -} - -#[test] -fn fund_sign_raw_transaction() { - let server = spawn_rpc_server(None, None).unwrap(); - let url = server.0.to_string(); - println!("Server started at {url}"); - - let rpc = bitcoincore_rpc::Client::new(url.as_str(), bitcoincore_rpc::Auth::None).unwrap(); - - let address = rpc.get_new_address(None, None).unwrap().assume_checked(); - - let txout = TxOut { - value: Amount::from_sat(0x45), - script_pubkey: address.script_pubkey(), - }; - let tx = Transaction { - input: vec![], - output: vec![txout], - version: Version::TWO, - lock_time: bitcoin::absolute::LockTime::Blocks(Height::ZERO), - }; - - // Insufficient funds. - if rpc.send_raw_transaction(&tx).is_ok() { - assert!(false); - } - - let new_tx = rpc.fund_raw_transaction(&tx, None, None).unwrap(); - assert_ne!(new_tx.change_position, -1); - let new_tx = deserialize::(&new_tx.hex).unwrap(); - assert_ne!(tx, new_tx); - - // Non signed input. - if rpc.send_raw_transaction(&tx).is_ok() { - assert!(false); - } - - let res = rpc - .sign_raw_transaction_with_wallet(&new_tx, None, None) - .unwrap(); - let new_tx = deserialize::(&res.hex).unwrap(); - - assert!(!new_tx.input.first().unwrap().witness.is_empty()); - - rpc.send_raw_transaction(&new_tx).unwrap(); -} From 535e94207aaaa06c713d34ebebccb08b13cd3b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 15:04:52 +0300 Subject: [PATCH 05/10] cargo: Mark some deps as optional for rpc_server feature. --- Cargo.toml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1b6cde3..a21c00f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,13 +13,16 @@ thiserror = "1.0.63" bitcoin-scriptexec = { git = "https://github.com/Bitcoin-Wildlife-Sanctuary/rust-bitcoin-scriptexec" } rusqlite = { version = "0.32.1", features = ["bundled"] } rs_merkle = "1.4" -jsonrpsee = { version = "0.24.3", features = ["server", "client", "macros"], default-features = false } -tokio = { version = "1.39.3", features = ["full"]} tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tower = "0.4.13" clap = { version = "4.5.16", features = ["derive"] } +jsonrpsee = { version = "0.24.3", features = ["server", "client", "macros"], default-features = false, optional = true } +tokio = { version = "1.39.3", features = ["full"], optional = true } +tower = { version = "0.4.13", optional = true } + +[dev-dependencies] +tokio = { version = "1.39.3", features = ["full"] } [features] # Enables RPC server interface. Note: Not stable nor complete. Use it in your own caution. -rpc_server = [] +rpc_server = ["dep:jsonrpsee", "dep:tokio", "dep:tower"] From 1eb9b6d4f797ef6b56f8b0eba427117de8af034d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 15:13:00 +0300 Subject: [PATCH 06/10] readme: Remove RPC server info. --- README.md | 51 ++++++--------------------------------------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index d1fe7e5..2f3afe1 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,11 @@ # Bitcoin Mock Remote Procedure Call -Bitcoin-mock-rpc is a mock Bitcoin ledger with RPC interface but without a -wallet support. Meaning there are only checks for consensus details of an -operation. This library can be used to test Bitcoin applications, without -needing to set up Bitcoin and with a **sandboxed environment**, for each test. - -Bitcoin-mock-rpc is built on -[bitcoincore-rpc's](https://github.com/rust-bitcoin/rust-bitcoincore-rpc) -`RpcApi` trait. Meaning no real servers are needed for Rust applications. There -is also an RPC server that can communicate with any application: No rust -dependencies! +`bitcoin-mock-rpc` is a mock Bitcoin ledger without a wallet support built on +`RpcApi` trait in +[bitcoincore-rpc](https://github.com/rust-bitcoin/rust-bitcoincore-rpc) library. +Meaning there are only checks for consensus details of an operation. This +library can be used to test Bitcoin applications, without needing to set up +Bitcoin and with a **sandboxed environment**, for each test. This library is aimed to help the development of [Clementine](https://github.com/chainwayxyz/clementine). Therefore, it's usage @@ -33,41 +29,6 @@ than the real one, please check function comments in ## Usage -### RPC Server - -RPC server can be spawned as long as there are available ports for them. Each -server will have an independent blockchain. - -To run from CLI: - -```bash -$ cargo run -Server started at 127.0.0.1:1024 -# ^^^^^^^^^^^^^^ -# Use this address in applications -$ cargo run -- --help # Prints usage information -``` - -To run in a Rust application: - -```rust -#[test] -fn test() { - // Calling `spawn_rpc_server` in a different test while this test is running - // is OK and will spawn another blockchain. If parameters are the same - // however, they will operate on the same blockchain. Note: (None, None) - // will result to pick random values. - let address = bitcoin_mock_rpc::spawn_rpc_server(None, None).await.unwrap(); - - let rpc = - bitcoincore_rpc::Client::new(&address.to_string(), bitcoincore_rpc::Auth::None).unwrap(); - - // Use `bitcoincore_rpc` as is from now on. No code change is needed. -} -``` - -### `RpcApiWrapper` Trait For Rust Applications - `RpcApiWrapper` trait can be used to select between real and mock RPC: ```rust From 111a359185b115c35bd232d3ec7d68b094f38144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 15:17:56 +0300 Subject: [PATCH 07/10] readme: Reorg headers. --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2f3afe1..52430c3 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,6 @@ of this library can be taken as a reference. not gives any guarantee to act as the Bitcoin itself at any scale. Use it at your own risk. -## Differences Between Real Bitcoin RPC and Feature Set - -This library is currently **under heavy development**. And it is not expected to -provide a full Bitcoin experience. Code needs to be checked for what really is -available as futures. Also, [changelog](CHANGELOG.md) is a great summary for -what's available. - -Some of the RPC functions behave similarly with real RPC while some of them are -not (mostly wallet operations). To check if an RPC function behaves different -than the real one, please check function comments in -[`src/client/rpc_api.rs`](src/client/rpc_api.rs). - ## Usage `RpcApiWrapper` trait can be used to select between real and mock RPC: @@ -59,6 +47,18 @@ fn test() { } ``` +## Differences Between Real Bitcoin RPC and Feature Set + +This library is currently **under heavy development**. And it is not expected to +provide a full Bitcoin experience. Code needs to be checked for what really is +available as futures. Also, [changelog](CHANGELOG.md) is a great summary for +what's available. + +Some of the RPC functions behave similarly with real RPC while some of them are +not (mostly wallet operations). To check if an RPC function behaves different +than the real one, please check function comments in +[`src/client/rpc_api.rs`](src/client/rpc_api.rs). + ## Testing Standard Rust tools are sufficient for testing: From 339771731b00727a1d3f2e833f25db860b7afb36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 15:20:31 +0300 Subject: [PATCH 08/10] lib.rs: Small doc update. --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 12cef37..c73c927 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,7 @@ //! # Bitcoin Mock Remote Procedure Call //! //! This library mocks [bitcoincore-rpc](https://github.com/rust-bitcoin/rust-bitcoincore-rpc) -//! library. This mock takes the advantage of `bitcoincore-rpc` trait interface -//! called `RpcApi`. +//! library. This mock takes advantage of `RpcApi` trait. //! //! Applications can implement another trait that will switch between this mock //! and the real RPC interface, for tests and production respectively. From 19f9bed2e9e13e83eb9dc691cd5ca6068100144a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 15:22:25 +0300 Subject: [PATCH 09/10] rpc: Rename decode_from_hex. --- src/rpc/adapter/blockchain.rs | 6 +++--- src/rpc/adapter/rawtransactions.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rpc/adapter/blockchain.rs b/src/rpc/adapter/blockchain.rs index edb2239..ee7bdfd 100644 --- a/src/rpc/adapter/blockchain.rs +++ b/src/rpc/adapter/blockchain.rs @@ -1,6 +1,6 @@ //! # Blockchain RPCs -use crate::utils::{decode_from_hex, encode_to_hex}; +use crate::utils::{_decode_from_hex, encode_to_hex}; use crate::Client; use bitcoin::{BlockHash, Txid}; use bitcoincore_rpc::{json, Error, RpcApi}; @@ -18,7 +18,7 @@ pub fn getblock( blockhash: String, verbosity: Option, ) -> Result { - let blockhash = decode_from_hex::(blockhash)?; + let blockhash = _decode_from_hex::(blockhash)?; tracing::trace!("Decoded block hash: {blockhash:?}"); let block = client.get_block(&blockhash)?; @@ -48,7 +48,7 @@ pub fn getblockheader( blockhash: String, verbose: Option, ) -> Result { - let blockhash = decode_from_hex::(blockhash)?; + let blockhash = _decode_from_hex::(blockhash)?; let header = client.get_block_header(&blockhash)?; match verbose { diff --git a/src/rpc/adapter/rawtransactions.rs b/src/rpc/adapter/rawtransactions.rs index 397b2d9..b32af7c 100644 --- a/src/rpc/adapter/rawtransactions.rs +++ b/src/rpc/adapter/rawtransactions.rs @@ -128,7 +128,7 @@ mod tests { use crate::{ ledger, rpc::adapter::GetrawtransactionReturn, - utils::{decode_from_hex, encode_to_hex}, + utils::{_decode_from_hex, encode_to_hex}, Client, RpcApiWrapper, }; use bitcoin::{ @@ -160,7 +160,7 @@ mod tests { let encoded_tx = super::getrawtransaction(&client, txid.to_string(), None, None).unwrap(); if let GetrawtransactionReturn::NoneVerbose(encoded_tx) = encoded_tx { - assert_eq!(tx, decode_from_hex(encoded_tx).unwrap()); + assert_eq!(tx, _decode_from_hex(encoded_tx).unwrap()); } else { panic!(""); } @@ -235,7 +235,7 @@ mod tests { }; let txid = super::sendrawtransaction(&client, encode_to_hex(&tx.clone()), None).unwrap(); - let txid = decode_from_hex::(txid).unwrap(); + let txid = _decode_from_hex::(txid).unwrap(); let read_tx = client.get_raw_transaction(&txid, None).unwrap(); From 12cef1f419162c1cdde598b310d33544f43a4816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 5 Sep 2024 15:28:32 +0300 Subject: [PATCH 10/10] changelog: Add new changes. --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cb10e3..31bd61f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- RPC server interface is disabled by default + - It can be enabled by a feature flag + ## [0.0.10] - 2024-09-04 ### Changed @@ -141,6 +148,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `generate_to_address` - `get_balance` +[Unreleased]: https://github.com/chainwayxyz/bitcoin-mock-rpc/compare/v0.0.10...HEAD [0.0.10]: https://github.com/chainwayxyz/bitcoin-mock-rpc/compare/v0.0.9...v0.0.10 [0.0.9]: https://github.com/chainwayxyz/bitcoin-mock-rpc/compare/v0.0.8...v0.0.9 [0.0.8]: https://github.com/chainwayxyz/bitcoin-mock-rpc/compare/v0.0.7...v0.0.8