From a3dec90dc108e65e4adafe5a618c16e6d78a9016 Mon Sep 17 00:00:00 2001 From: Danylo Ostapchenko Date: Tue, 13 Feb 2024 13:12:16 +0200 Subject: [PATCH] Implement `getblock` with verbosity value `2` --- client/src/client.rs | 7 ++++-- integration_test/src/main.rs | 4 +-- json/src/lib.rs | 49 ++++++++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/client/src/client.rs b/client/src/client.rs index 55df6480..3fcfe829 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -21,7 +21,7 @@ use jsonrpc; use serde; use serde_json; -use crate::bitcoin::address::{NetworkUnchecked, NetworkChecked}; +use crate::bitcoin::address::{NetworkChecked, NetworkUnchecked}; use crate::bitcoin::hashes::hex::FromHex; use crate::bitcoin::secp256k1::ecdsa::Signature; use crate::bitcoin::{ @@ -343,7 +343,10 @@ pub trait RpcApi: Sized { fn get_block_info(&self, hash: &bitcoin::BlockHash) -> Result { self.call("getblock", &[into_json(hash)?, 1.into()]) } - //TODO(stevenroose) add getblock_txs + + fn get_block_txs(&self, hash: &bitcoin::BlockHash) -> Result { + self.call("getblock", &[into_json(hash)?, 2.into()]) + } fn get_block_header(&self, hash: &bitcoin::BlockHash) -> Result { let hex: String = self.call("getblockheader", &[into_json(hash)?, false.into()])?; diff --git a/integration_test/src/main.rs b/integration_test/src/main.rs index 3c82d59a..2dfe3f47 100644 --- a/integration_test/src/main.rs +++ b/integration_test/src/main.rs @@ -328,8 +328,8 @@ fn test_get_block(cl: &Client) { let tip = cl.get_best_block_hash().unwrap(); let info = cl.get_block_info(&tip).unwrap(); - assert_eq!(info.hash, tip); - assert_eq!(info.confirmations, 1); + assert_eq!(info.common.hash, tip); + assert_eq!(info.common.confirmations, 1); } fn test_get_block_header_get_block_header_info(cl: &Client) { diff --git a/json/src/lib.rs b/json/src/lib.rs index 5c654353..c6e7379b 100644 --- a/json/src/lib.rs +++ b/json/src/lib.rs @@ -24,15 +24,17 @@ extern crate serde_json; use std::collections::HashMap; - use bitcoin::address::NetworkUnchecked; use bitcoin::block::Version; use bitcoin::consensus::encode; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::sha256; -use bitcoin::{Address, Amount, PrivateKey, PublicKey, SignedAmount, Transaction, ScriptBuf, Script, bip158, bip32, Network}; +use bitcoin::{ + bip158, bip32, Address, Amount, Network, PrivateKey, PublicKey, Script, ScriptBuf, + SignedAmount, Transaction, +}; use serde::de::Error as SerdeError; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; use std::fmt; //TODO(stevenroose) consider using a Time type @@ -193,7 +195,7 @@ impl Eq for ScanningDetails {} #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct GetBlockResult { +pub struct BlockData { pub hash: bitcoin::BlockHash, pub confirmations: i32, pub size: usize, @@ -204,7 +206,6 @@ pub struct GetBlockResult { #[serde(default, with = "crate::serde_hex::opt")] pub version_hex: Option>, pub merkleroot: bitcoin::hash_types::TxMerkleNode, - pub tx: Vec, pub time: usize, pub mediantime: Option, pub nonce: u32, @@ -217,6 +218,44 @@ pub struct GetBlockResult { pub nextblockhash: Option, } +#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetBlockResult { + #[serde(flatten)] + pub common: BlockData, + pub tx: Vec, +} + +#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetBlockTxResult { + #[serde(flatten)] + pub common: BlockData, + #[serde(deserialize_with = "deserialize_tx")] + pub tx: Vec, +} + +fn deserialize_tx<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Debug, Deserialize)] + struct TxWrapper { + pub hex: String, + } + + let tx_wrappers: Vec = Deserialize::deserialize(deserializer)?; + let transactions: Result, _> = tx_wrappers + .into_iter() + .map(|wrapper| { + let bytes: Vec = FromHex::from_hex(&wrapper.hex).unwrap(); + Ok(bitcoin::consensus::encode::deserialize(&bytes).unwrap()) + }) + .collect(); + + transactions +} + #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct GetBlockHeaderResult {