Skip to content

Commit

Permalink
Merge pull request #38 from tcharding/12-19-test
Browse files Browse the repository at this point in the history
Test everything in the `blockchain` section for v17 and v18
  • Loading branch information
tcharding authored Dec 19, 2024
2 parents 1484d9a + 3625782 commit 30bce38
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 90 deletions.
6 changes: 3 additions & 3 deletions client/src/client_sync/v17/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ macro_rules! impl_client_v17__gettxout {
macro_rules! impl_client_v17__gettxoutproof {
() => {
impl Client {
pub fn get_tx_out_proof(&self, txids: Vec<Txid>) -> Result<GetTxOut> {
pub fn get_tx_out_proof(&self, txids: &[Txid]) -> Result<String> {
self.call("gettxoutproof", &[into_json(txids)?])
}
}
Expand All @@ -266,7 +266,7 @@ macro_rules! impl_client_v17__gettxoutproof {
macro_rules! impl_client_v17__gettxoutsetinfo {
() => {
impl Client {
pub fn get_tx_out_set_info(&self) -> Result<GetTxOut> {
pub fn get_tx_out_set_info(&self) -> Result<GetTxOutSetInfo> {
self.call("gettxoutsetinfo", &[])
}
}
Expand All @@ -279,7 +279,7 @@ macro_rules! impl_client_v17__verifytxoutproof {
() => {
impl Client {
// `proof` is the hex-encoded proof generated by `gettxoutproof`.
pub fn verify_tx_out_proof(&self, proof: &str) -> Result<GetTxOut> {
pub fn verify_tx_out_proof(&self, proof: &str) -> Result<VerifyTxOutProof> {
self.call("verifytxoutproof", &[into_json(proof)?])
}
}
Expand Down
4 changes: 4 additions & 0 deletions client/src/client_sync/v18.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ crate::impl_client_v17__getmempooldescendants!();
crate::impl_client_v17__getmempoolentry!();
crate::impl_client_v17__getmempoolinfo!();
crate::impl_client_v17__getrawmempool!();
crate::impl_client_v17__gettxout!();
crate::impl_client_v17__gettxoutproof!();
crate::impl_client_v17__gettxoutsetinfo!();
crate::impl_client_v17__verifytxoutproof!();

// == Control ==
crate::impl_client_v17__getmemoryinfo!();
Expand Down
31 changes: 21 additions & 10 deletions integration_test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,19 @@ pub trait NodeExt {
/// Generates [`NBLOCKS`] to an address controlled by the loaded wallet.
fn fund_wallet(&self);

/// Mine a block.
/// Mines a block.
///
/// Should send mining reward to a new address for the loaded wallet.
fn mine_a_block(&self);

/// Create a transaction and mine it.
/// Creates a transaction in the mempool.
///
/// # Returns
///
/// The receive address and the transaction.
fn create_mempool_transaction(&self) -> (bitcoin::Address, bitcoin::Txid);

/// Creates a transaction and mines a block that includes it in the chain.
///
/// # Returns
///
Expand All @@ -77,12 +84,22 @@ impl NodeExt for Node {
self.client.generate_to_address(NBLOCKS, &address).expect("failed to generate to address");
}

fn create_mined_transaction(&self) -> (bitcoin::Address, bitcoin::Transaction) {
fn mine_a_block(&self) {
let address = self.client.new_address().expect("failed to get new address");
self.client.generate_to_address(1, &address).expect("failed to generate to address");
}

fn create_mempool_transaction(&self) -> (bitcoin::Address, bitcoin::Txid) {
const MILLION_SATS: bitcoin::Amount = bitcoin::Amount::from_sat(1000000);

let address = self.client.new_address().expect("failed to get new address");

let _ = self.client.send_to_address(&address, MILLION_SATS);
let txid = self.client.send_to_address(&address, MILLION_SATS).expect("failed to send to address").txid().expect("failed to convert hex to txid");
(address, txid)
}

fn create_mined_transaction(&self) -> (bitcoin::Address, bitcoin::Transaction) {
let (address, _) = self.create_mempool_transaction();
self.mine_a_block();

let best_block_hash = self.client.best_block_hash().expect("best_block_hash");
Expand All @@ -91,12 +108,6 @@ impl NodeExt for Node {

(address, tx)
}

fn mine_a_block(&self) {
// TODO: Consider returning the error.
let address = self.client.new_address().expect("failed to get new address");
self.client.generate_to_address(1, &address).expect("failed to generate to address");
}
}

/// Return a temporary file path.
Expand Down
96 changes: 81 additions & 15 deletions integration_test/tests/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,37 +134,103 @@ fn get_difficulty() {

#[test]
#[cfg(feature = "TODO")]
fn get_mempool_ancestors() { todo!() }
fn get_mempool_ancestors() {
// We can probably get away with not testing this because it returns the
// same type as `getmempoolentry` which is tested below.
}

#[test]
#[cfg(feature = "TODO")]
fn get_mempool_descendants() { todo!() }
fn get_mempool_descendants() {
// We can probably get away with not testing this because it returns the
// same type as `getmempoolentry` which is tested below.
}

#[test]
#[cfg(feature = "TODO")]
fn get_mempool_entry() { todo!() }
fn get_mempool_entry() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, txid) = node.create_mempool_transaction();

let json = node.client.get_mempool_entry(txid).expect("getmempoolentry");
assert!(json.into_model().is_ok());
}

#[test]
#[cfg(feature = "TODO")]
fn get_mempool_info() { todo!() }
fn get_mempool_info() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, _txid) = node.create_mempool_transaction();

// Test the type and into model conversion code.
let json = node.client.get_mempool_info().expect("getmempoolinfo");
let info = json.into_model().expect("into_model");
// Sanity check.
assert_eq!(info.size, 1);
}

#[test]
#[cfg(feature = "TODO")]
fn get_raw_mempool() { todo!() }
fn get_raw_mempool() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, _txid) = node.create_mempool_transaction();

// Test the type and into model conversion code.
let json = node.client.get_raw_mempool().expect("getrawmempool");
let mempool = json.into_model().expect("into_model");
// Sanity check.
assert_eq!(mempool.0.len(), 1);
}

#[test]
// FIXME: Fails with getrawmempool verbose: JsonRpc(Json(Error("invalid type: map, expected a sequence", line: 1, column: 0)))
#[cfg(feature = "TODO")]
fn get_tx_out() { todo!() }
fn get_raw_mempool_verbose() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, _txid) = node.create_mempool_transaction();

// Test the type and into model conversion code.
let json = node.client.get_raw_mempool_verbose().expect("getrawmempool verbose");
let mempool = json.into_model().expect("into_model");
// Sanity check.
assert_eq!(mempool.0.len(), 1);
}

#[test]
#[cfg(feature = "TODO")]
fn get_tx_out_proof() { todo!() }
fn get_tx_out() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, tx) = node.create_mined_transaction();
let txid = tx.compute_txid();

// Test the type and into model conversion code.
let json = node.client.get_tx_out(txid, 1).expect("gettxout");
let _ = json.into_model().expect("into_model");
}

#[test]
#[cfg(feature = "TODO")]
fn get_tx_out_set_info() { todo!() }
fn get_tx_out_set_info() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, _tx) = node.create_mined_transaction();

// Test the type and into model conversion code.
let json = node.client.get_tx_out_set_info().expect("gettxoutsetinfo");
let _ = json.into_model().expect("into_model");

}

// Implicitly tests the omitted method `gettxoutproof` as well.
#[test]
#[cfg(feature = "TODO")]
fn verify_tx_out_proof() { todo!() }
fn verify_tx_out_proof() {
let node = Node::new_with_default_wallet();
node.fund_wallet();
let (_address, tx) = node.create_mined_transaction();
let txid = tx.compute_txid();

let proof = node.client.get_tx_out_proof(&[txid]).expect("gettxoutproof");

let txids = node.client.verify_tx_out_proof(&proof).expect("verifytxoutproof");
assert_eq!(txids.0.len(), 1);
}
6 changes: 6 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
set export

REPO_DIR := `git rev-parse --show-toplevel`

default:
@just --list

Expand All @@ -12,10 +16,12 @@ check:
# Lint everything.
lint:
cargo +$(cat ./nightly-version) clippy --workspace --all-targets --all-features -- --deny warnings
cd $REPO_DIR/node > /dev/null; cargo +$(cat ../nightly-version) clippy --all-targets --all-features -- --deny warnings

# Run cargo fmt
fmt:
cargo +$(cat ./nightly-version) fmt --all
cd $REPO_DIR/node > /dev/null; cargo +$(cat ../nightly-version) fmt

# Check the formatting
format:
Expand Down
9 changes: 5 additions & 4 deletions node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,9 @@ impl Node {
match client_base.create_wallet(wallet) {
Ok(json) => {
debug!("created wallet: {}", json.name());
},
}
Err(e) => {
debug!("initial create_wallet unsuccessful, try loading instead: {:?}", e);
debug!("initial create_wallet failed, try load instead: {:?}", e);
let wallet = client_base.load_wallet(wallet)?.name();
debug!("loaded wallet: {}", wallet);
}
Expand Down Expand Up @@ -577,9 +577,9 @@ mod test {
use tempfile::TempDir;

use super::*;
use crate::{exe_path, get_available_port, Node, Conf, LOCAL_IP};
#[cfg(not(feature = "28_0"))]
use crate::P2P;
use crate::{exe_path, get_available_port, Conf, Node, LOCAL_IP};

#[test]
fn test_local_ip() {
Expand Down Expand Up @@ -706,7 +706,8 @@ mod test {
let node2 = Node::with_conf(&exe, &conf_node2).unwrap();

// Create Node 3 Connected To Node
let conf_node3 = Conf::<'_> { p2p: node2.p2p_connect(false).unwrap(), ..Default::default() };
let conf_node3 =
Conf::<'_> { p2p: node2.p2p_connect(false).unwrap(), ..Default::default() };
let node3 = Node::with_conf(exe_path().unwrap(), &conf_node3).unwrap();

// Get each nodes Peers
Expand Down
20 changes: 18 additions & 2 deletions node/src/versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ pub const VERSION: &str = "0.18.1";
pub const VERSION: &str = "0.17.1";

// To make --no-default-features work we have to enable some feature, use most recent version same as for default.
#[cfg(all(not(feature = "28_0"), not(feature = "27_1"), not(feature = "27_0"), not(feature = "26_2"), not(feature = "26_1"), not(feature = "26_0"), not(feature = "25_2"), not(feature = "24_2"), not(feature = "23_2"), not(feature = "22_1"), not(feature = "0_21_2"), not(feature = "0_20_2"), not(feature = "0_19_1"), not(feature = "0_18_1"), not(feature = "0_17_1")))]
#[allow(dead_code)] // for --no-default-features
#[cfg(all(
not(feature = "28_0"),
not(feature = "27_1"),
not(feature = "27_0"),
not(feature = "26_2"),
not(feature = "26_1"),
not(feature = "26_0"),
not(feature = "25_2"),
not(feature = "24_2"),
not(feature = "23_2"),
not(feature = "22_1"),
not(feature = "0_21_2"),
not(feature = "0_20_2"),
not(feature = "0_19_1"),
not(feature = "0_18_1"),
not(feature = "0_17_1")
))]
#[allow(dead_code)] // for --no-default-features
pub const VERSION: &str = "28.0";
8 changes: 0 additions & 8 deletions types/src/v17/blockchain/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,14 +502,6 @@ impl GetTxOut {
}
}

impl GetTxOutProof {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::GetTxOutProof, hex::HexToBytesError> {
let data = Vec::from_hex(&self.0)?;
Ok(model::GetTxOutProof(data))
}
}

impl GetTxOutSetInfo {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::GetTxOutSetInfo, GetTxOutSetInfoError> {
Expand Down
24 changes: 1 addition & 23 deletions types/src/v17/blockchain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ pub struct GetTxOut {
/// The transaction value in BTC.
pub value: f64,
/// The script pubkey.
#[serde(rename = "scriptPubkey")]
#[serde(rename = "scriptPubKey")]
pub script_pubkey: ScriptPubkey,
/// Coinbase or not.
pub coinbase: bool,
Expand All @@ -621,28 +621,6 @@ pub struct ScriptPubkey {
pub addresses: Vec<String>,
}

/// Result of JSON-RPC method `gettxoutproof`.
///
/// > gettxoutproof ["txid",...] ( blockhash )
/// >
/// > Returns a hex-encoded proof that "txid" was included in a block.
/// >
/// > NOTE: By default this function only works sometimes. This is when there is an
/// > unspent output in the utxo for this transaction. To make it always work,
/// > you need to maintain a transaction index, using the -txindex command line option or
/// > specify the block in which the transaction is included manually (by blockhash).
/// >
/// > Arguments:
/// > 1. "txids" (string) A json array of txids to filter
/// > [
/// > "txid" (string) A transaction hash
/// > ,...
/// > ]
///
/// Inner field is a string that is a serialized, hex-encoded data for the proof.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct GetTxOutProof(pub String);

/// Result of JSON-RPC method `gettxoutsetinfo`.
///
/// > gettxoutsetinfo
Expand Down
18 changes: 9 additions & 9 deletions types/src/v17/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@
//! | getdifficulty | done |
//! | getmempoolancestors | done (untested) |
//! | getmempooldescendants | done (untested) |
//! | getmempoolentry | done (untested) |
//! | getmempoolinfo | done (untested) |
//! | getrawmempool | done (untested) |
//! | gettxout | done (untested) |
//! | gettxoutproof | done (untested) |
//! | gettxoutsetinfo | done (untested) |
//! | getmempoolentry | done |
//! | getmempoolinfo | done |
//! | getrawmempool | done |
//! | gettxout | done |
//! | gettxoutproof | omitted |
//! | gettxoutsetinfo | done |
//! | preciousblock | omitted |
//! | pruneblockchain | omitted |
//! | savemempool | omitted |
//! | scantxoutset | omitted |
//! | verifychain | omitted |
//! | verifytxoutproof | done (untested) |
//! | verifytxoutproof | done |
//!
//! </details>
//!
Expand Down Expand Up @@ -237,8 +237,8 @@ pub use self::{
GetBlockVerbosityOne, GetBlockVerbosityZero, GetBlockchainInfo, GetChainTips,
GetChainTxStats, GetDifficulty, GetMempoolAncestors, GetMempoolAncestorsVerbose,
GetMempoolDescendants, GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo,
GetRawMempool, GetRawMempoolVerbose, GetTxOut, GetTxOutProof, GetTxOutSetInfo,
MempoolEntry, MempoolEntryFees, ScriptPubkey, Softfork, SoftforkReject, VerifyTxOutProof,
GetRawMempool, GetRawMempoolVerbose, GetTxOut, GetTxOutSetInfo, MempoolEntry,
MempoolEntryFees, ScriptPubkey, Softfork, SoftforkReject, VerifyTxOutProof,
},
control::{GetMemoryInfoStats, Locked, Logging, Uptime},
generating::{Generate, GenerateToAddress},
Expand Down
Loading

0 comments on commit 30bce38

Please sign in to comment.