Skip to content

Commit

Permalink
Merge pull request #62 from chainwayxyz/rpc_server_encode_decode_bug_…
Browse files Browse the repository at this point in the history
…fixes

Rpc server encode decode bug fixes
  • Loading branch information
ceyhunsen authored Sep 5, 2024
2 parents 40b47bb + 12cef1f commit 1503836
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 333 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
14 changes: 9 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +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 }

[[bin]]
name = "bitcoin_mock_rpc"
[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 = ["dep:jsonrpsee", "dep:tokio", "dep:tower"]
75 changes: 18 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -19,55 +15,8 @@ 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

### 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
Expand Down Expand Up @@ -98,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:
Expand Down
61 changes: 0 additions & 61 deletions src/bin/bitcoin_mock_rpc.rs

This file was deleted.

4 changes: 2 additions & 2 deletions src/client/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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::<Transaction>(new_tx).unwrap();
let new_tx = _decode_from_hex::<Transaction>(new_tx).unwrap();

assert_eq!(tx, new_tx);
assert_eq!(res.change_position, -1);
Expand Down
2 changes: 1 addition & 1 deletion src/ledger/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<BlockHash, LedgerError> {
let mut transactions = self.get_mempool_transactions();
let coinbase_transaction = self.create_coinbase_transaction(
Expand Down
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//! # 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.
pub mod client;
mod ledger;
pub mod rpc;
mod utils;

// Re-imports.
pub use client::*;

#[cfg(feature = "rpc_server")]
pub mod rpc;
6 changes: 3 additions & 3 deletions src/rpc/adapter/blockchain.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -18,7 +18,7 @@ pub fn getblock(
blockhash: String,
verbosity: Option<usize>,
) -> Result<String, Error> {
let blockhash = decode_from_hex::<BlockHash>(blockhash)?;
let blockhash = _decode_from_hex::<BlockHash>(blockhash)?;
tracing::trace!("Decoded block hash: {blockhash:?}");

let block = client.get_block(&blockhash)?;
Expand Down Expand Up @@ -48,7 +48,7 @@ pub fn getblockheader(
blockhash: String,
verbose: Option<bool>,
) -> Result<String, Error> {
let blockhash = decode_from_hex::<BlockHash>(blockhash)?;
let blockhash = _decode_from_hex::<BlockHash>(blockhash)?;
let header = client.get_block_header(&blockhash)?;

match verbose {
Expand Down
Loading

0 comments on commit 1503836

Please sign in to comment.