From 30250d80c6d71379cc911e3fb2e5ebfc4296670c Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Mon, 20 May 2024 10:29:10 +1000 Subject: [PATCH] Add initial RPC calls using jsonrcp-client We would like to test the `bitcoincore-rpc-json` crate without depending on `bitcoincore-rpc` - the point being that users of the crate should be able to use what ever RCP client they want. Add infrastructure and a few initial RPC calls to see what it looks like to test `json` using the `jsonrpc-client` crate. The `run.sh` script is just a quick copy and hack of the other one here. The aim is to eventually test the `json` RPC types against specific versions of Core to make sure we have them correct as Core changes. --- .../jsonrpc-client/Cargo.toml | 18 +++++++ json/integration_test/jsonrpc-client/run.sh | 52 +++++++++++++++++++ .../jsonrpc-client/src/lib.rs | 3 ++ .../jsonrpc-client/src/main.rs | 36 +++++++++++++ .../jsonrpc-client/src/v22.rs | 34 ++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 json/integration_test/jsonrpc-client/Cargo.toml create mode 100755 json/integration_test/jsonrpc-client/run.sh create mode 100644 json/integration_test/jsonrpc-client/src/lib.rs create mode 100644 json/integration_test/jsonrpc-client/src/main.rs create mode 100644 json/integration_test/jsonrpc-client/src/v22.rs diff --git a/json/integration_test/jsonrpc-client/Cargo.toml b/json/integration_test/jsonrpc-client/Cargo.toml new file mode 100644 index 00000000..a02fa453 --- /dev/null +++ b/json/integration_test/jsonrpc-client/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "integration-test" +version = "0.1.0" +authors = ["Tobin C. Harding "] +license = "CC0-1.0" +edition = "2021" + +[dependencies] +bitcoincore-rpc-json = { path = "../.." } + +anyhow = "1" +jsonrpc_client = { version = "0.7", features = ["reqwest"] } +reqwest = "0.11" +tokio = { version = "1", features = [ "macros", "rt-multi-thread" ] } + +# Prevent this from interfering with workspaces. +[workspace] +members = ["."] diff --git a/json/integration_test/jsonrpc-client/run.sh b/json/integration_test/jsonrpc-client/run.sh new file mode 100755 index 00000000..3999b50c --- /dev/null +++ b/json/integration_test/jsonrpc-client/run.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +TESTDIR=/tmp/rust_bitcoincore_rpc_test + +if bitcoind -version | grep -q "v22"; then + echo "Starting two bitcoind v22 instances" +else + echo "Currently tests are intended for Bitcoin Core v22" + exit 1 +fi + +rm -rf ${TESTDIR} +mkdir -p ${TESTDIR}/1 ${TESTDIR}/2 + +bitcoind -regtest \ + -datadir=${TESTDIR}/1 \ + -port=12348 \ + -server=0 \ + -printtoconsole=0 & +PID1=$! + +# Make sure it's listening on its p2p port. +sleep 1 + +bitcoind -regtest \ + -datadir=${TESTDIR}/2 \ + -connect=127.0.0.1:12348 \ + -rpcport=12349 \ + -rpcuser=user \ + -rpcpassword=password \ + -server=1 \ + -txindex=1 \ + -printtoconsole=0 \ + -zmqpubrawblock=tcp://0.0.0.0:28332 \ + -zmqpubrawtx=tcp://0.0.0.0:28333 & +PID2=$! + +# Let it connect to the other node. +sleep 1 + +echo "Two connected bitcoind instances running, hit port 12349" + +# RPC_URL=http://localhost:12349 \ +# RPC_COOKIE=${TESTDIR}/2/regtest/.cookie \ +# TESTDIR=${TESTDIR} \ +# cargo run + +# RESULT=$? + +# kill -9 $PID1 $PID2 + +# exit $RESULT diff --git a/json/integration_test/jsonrpc-client/src/lib.rs b/json/integration_test/jsonrpc-client/src/lib.rs new file mode 100644 index 00000000..f7995189 --- /dev/null +++ b/json/integration_test/jsonrpc-client/src/lib.rs @@ -0,0 +1,3 @@ +//! Test the `bitcoincore-rpc-json` crate. + +pub mod v22; diff --git a/json/integration_test/jsonrpc-client/src/main.rs b/json/integration_test/jsonrpc-client/src/main.rs new file mode 100644 index 00000000..f4bd996b --- /dev/null +++ b/json/integration_test/jsonrpc-client/src/main.rs @@ -0,0 +1,36 @@ +use std::fmt; + +use anyhow::Result; +use integration_test::v22::{self, BitcoindRpc}; + +/// Set to `true` for verbose output. +const VERBOSE: bool = true; + +#[tokio::main] +async fn main() -> Result<()> { + let username = "user"; + let password = "password"; + + let url = format!("http://{}:{}@localhost:12349", username, password); + println!("url: {}", url); + + let client = v22::Client::new(url)?; + + let res = client.getblockchaininfo().await?; + print(res); + + let res = client.getnetworkinfo().await?; + print(res); + + let res = client.getindexinfo().await?; + print(res); + + Ok(()) +} + +/// Prints `res` if `VERBOSE` is set to `true`. +fn print(res: T) { + if VERBOSE { + println!("{:#?}", res); + } +} diff --git a/json/integration_test/jsonrpc-client/src/v22.rs b/json/integration_test/jsonrpc-client/src/v22.rs new file mode 100644 index 00000000..974a0646 --- /dev/null +++ b/json/integration_test/jsonrpc-client/src/v22.rs @@ -0,0 +1,34 @@ +//! Test the Bitcoin Core v22 JSON-RPC API. + +use anyhow; +use bitcoincore_rpc_json::*; + +/// An RPC client. +#[jsonrpc_client::implement(BitcoindRpc)] +pub struct Client { + inner: reqwest::Client, + base_url: jsonrpc_client::Url, +} + +impl Client { + /// Creates a new [`Client`]. + pub fn new(base_url: String) -> anyhow::Result { + Ok(Self { + inner: reqwest::Client::new(), + base_url: base_url.parse()?, + }) + } +} + +/// Implement JSON-RPC call: `getblockchaininfo`. +#[jsonrpc_client::api(version = "1.0")] +pub trait BitcoindRpc { + /// Implement JSON-RPC call: `getblockchaininfo`. + async fn getblockchaininfo(&self) -> GetBlockchainInfoResult; + + /// Implement JSON-RPC call: `getnetworkinfo`. + async fn getnetworkinfo(&self) -> GetNetworkInfoResult; + + /// Implement JSON-RPC call: `getindexinfo`. + async fn getindexinfo(&self) -> GetIndexInfoResult; +}