use proper type for EsploraHeader, make conversion to BlockHeader infallible

This commit is contained in:
Riccardo Casatta 2020-11-17 15:08:04 +01:00
parent 3c8b8e4fca
commit 4d1617f4e0
No known key found for this signature in database
GPG Key ID: FD986A969E450397
2 changed files with 62 additions and 67 deletions

View File

@ -48,7 +48,7 @@ use serde::Deserialize;
use reqwest::{Client, StatusCode}; use reqwest::{Client, StatusCode};
use bitcoin::consensus::{deserialize, serialize}; use bitcoin::consensus::{deserialize, serialize};
use bitcoin::hashes::hex::{FromHex, ToHex}; use bitcoin::hashes::hex::ToHex;
use bitcoin::hashes::{sha256, Hash}; use bitcoin::hashes::{sha256, Hash};
use bitcoin::{BlockHash, BlockHeader, Script, Transaction, TxMerkleNode, Txid}; use bitcoin::{BlockHash, BlockHeader, Script, Transaction, TxMerkleNode, Txid};
@ -57,7 +57,6 @@ use super::*;
use crate::database::BatchDatabase; use crate::database::BatchDatabase;
use crate::error::Error; use crate::error::Error;
use crate::FeeRate; use crate::FeeRate;
use std::convert::TryInto;
#[derive(Debug)] #[derive(Debug)]
struct UrlClient { struct UrlClient {
@ -192,7 +191,7 @@ impl UrlClient {
let esplora_header = resp.json::<EsploraHeader>().await?; let esplora_header = resp.json::<EsploraHeader>().await?;
Ok(esplora_header.try_into()?) Ok(esplora_header.into())
} }
async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> { async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
@ -360,27 +359,23 @@ pub struct EsploraHeader {
pub tx_count: u32, pub tx_count: u32,
pub size: u32, pub size: u32,
pub weight: u32, pub weight: u32,
pub merkle_root: String, pub merkle_root: TxMerkleNode,
pub previousblockhash: String, pub previousblockhash: BlockHash,
pub nonce: u32, pub nonce: u32,
pub bits: u32, pub bits: u32,
pub difficulty: u32, pub difficulty: u32,
} }
impl TryInto<BlockHeader> for EsploraHeader { impl Into<BlockHeader> for EsploraHeader {
type Error = EsploraError; fn into(self) -> BlockHeader {
BlockHeader {
fn try_into(self) -> Result<BlockHeader, esplora::EsploraError> {
Ok(BlockHeader {
version: self.version, version: self.version,
prev_blockhash: BlockHash::from_hex(&self.previousblockhash) prev_blockhash: self.previousblockhash,
.map_err(|_| EsploraError::HeaderParseFail)?, merkle_root: self.merkle_root,
merkle_root: TxMerkleNode::from_hex(&self.merkle_root)
.map_err(|_| EsploraError::HeaderParseFail)?,
time: self.timestamp, time: self.timestamp,
bits: self.bits, bits: self.bits,
nonce: self.nonce, nonce: self.nonce,
}) }
} }
} }
@ -449,13 +444,12 @@ mod test {
use crate::blockchain::esplora::EsploraHeader; use crate::blockchain::esplora::EsploraHeader;
use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::hex::FromHex;
use bitcoin::{BlockHash, BlockHeader}; use bitcoin::{BlockHash, BlockHeader};
use std::convert::TryInto;
#[test] #[test]
fn test_esplora_header() { fn test_esplora_header() {
let json_str = r#"{"id":"00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206","height":1,"version":1,"timestamp":1296688928,"tx_count":1,"size":190,"weight":760,"merkle_root":"f0315ffc38709d70ad5647e22048358dd3745f3ce3874223c80a7c92fab0c8ba","previousblockhash":"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","nonce":1924588547,"bits":486604799,"difficulty":1}"#; let json_str = r#"{"id":"00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206","height":1,"version":1,"timestamp":1296688928,"tx_count":1,"size":190,"weight":760,"merkle_root":"f0315ffc38709d70ad5647e22048358dd3745f3ce3874223c80a7c92fab0c8ba","previousblockhash":"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","nonce":1924588547,"bits":486604799,"difficulty":1}"#;
let json: EsploraHeader = serde_json::from_str(&json_str).unwrap(); let json: EsploraHeader = serde_json::from_str(&json_str).unwrap();
let header: BlockHeader = json.try_into().unwrap(); let header: BlockHeader = json.into();
assert_eq!( assert_eq!(
header.block_hash(), header.block_hash(),
BlockHash::from_hex("00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206") BlockHash::from_hex("00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206")

View File

@ -309,56 +309,57 @@ pub fn make_cli_subcommands<'a, 'b>() -> App<'a, 'b> {
} }
pub fn add_global_flags<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { pub fn add_global_flags<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
let mut app = app.arg( let mut app = app
Arg::with_name("network") .arg(
.short("n") Arg::with_name("network")
.long("network") .short("n")
.value_name("NETWORK") .long("network")
.help("Sets the network") .value_name("NETWORK")
.takes_value(true) .help("Sets the network")
.default_value("testnet") .takes_value(true)
.possible_values(&["testnet", "regtest"]), .default_value("testnet")
) .possible_values(&["testnet", "regtest"]),
.arg( )
Arg::with_name("wallet") .arg(
.short("w") Arg::with_name("wallet")
.long("wallet") .short("w")
.value_name("WALLET_NAME") .long("wallet")
.help("Selects the wallet to use") .value_name("WALLET_NAME")
.takes_value(true) .help("Selects the wallet to use")
.default_value("main"), .takes_value(true)
) .default_value("main"),
.arg( )
Arg::with_name("proxy") .arg(
.short("p") Arg::with_name("proxy")
.long("proxy") .short("p")
.value_name("SERVER:PORT") .long("proxy")
.help("Sets the SOCKS5 proxy for the Electrum client") .value_name("SERVER:PORT")
.takes_value(true), .help("Sets the SOCKS5 proxy for the Electrum client")
) .takes_value(true),
.arg( )
Arg::with_name("descriptor") .arg(
.short("d") Arg::with_name("descriptor")
.long("descriptor") .short("d")
.value_name("DESCRIPTOR") .long("descriptor")
.help("Sets the descriptor to use for the external addresses") .value_name("DESCRIPTOR")
.required(true) .help("Sets the descriptor to use for the external addresses")
.takes_value(true), .required(true)
) .takes_value(true),
.arg( )
Arg::with_name("change_descriptor") .arg(
.short("c") Arg::with_name("change_descriptor")
.long("change_descriptor") .short("c")
.value_name("DESCRIPTOR") .long("change_descriptor")
.help("Sets the descriptor to use for internal addresses") .value_name("DESCRIPTOR")
.takes_value(true), .help("Sets the descriptor to use for internal addresses")
) .takes_value(true),
.arg( )
Arg::with_name("v") .arg(
.short("v") Arg::with_name("v")
.multiple(true) .short("v")
.help("Sets the level of verbosity"), .multiple(true)
); .help("Sets the level of verbosity"),
);
if cfg!(feature = "esplora") { if cfg!(feature = "esplora") {
app = app.arg( app = app.arg(