From 2f9bdc729c930659a73156cbd72251c0733d0b6c Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 1 Jul 2024 11:13:11 +0200 Subject: [PATCH] Prepare `convert.rs` --- lightning-block-sync/src/convert.rs | 182 +++++++++++++++------------- 1 file changed, 96 insertions(+), 86 deletions(-) diff --git a/lightning-block-sync/src/convert.rs b/lightning-block-sync/src/convert.rs index e3bf96220..fa2b61d54 100644 --- a/lightning-block-sync/src/convert.rs +++ b/lightning-block-sync/src/convert.rs @@ -13,20 +13,21 @@ use serde_json; use std::convert::From; use std::convert::TryFrom; use std::convert::TryInto; +use std::io; use std::str::FromStr; use bitcoin::hashes::Hash; impl TryInto for JsonResponse { - type Error = std::io::Error; - fn try_into(self) -> Result { Ok(self.0) } + type Error = io::Error; + fn try_into(self) -> Result { Ok(self.0) } } -/// Conversion from `std::io::Error` into `BlockSourceError`. -impl From for BlockSourceError { - fn from(e: std::io::Error) -> BlockSourceError { +/// Conversion from `io::Error` into `BlockSourceError`. +impl From for BlockSourceError { + fn from(e: io::Error) -> BlockSourceError { match e.kind() { - std::io::ErrorKind::InvalidData => BlockSourceError::persistent(e), - std::io::ErrorKind::InvalidInput => BlockSourceError::persistent(e), + io::ErrorKind::InvalidData => BlockSourceError::persistent(e), + io::ErrorKind::InvalidInput => BlockSourceError::persistent(e), _ => BlockSourceError::transient(e), } } @@ -34,11 +35,11 @@ impl From for BlockSourceError { /// Parses binary data as a block. impl TryInto for BinaryResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result { + fn try_into(self) -> io::Result { match encode::deserialize(&self.0) { - Err(_) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid block data")), + Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid block data")), Ok(block) => Ok(block), } } @@ -46,11 +47,11 @@ impl TryInto for BinaryResponse { /// Parses binary data as a block hash. impl TryInto for BinaryResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result { + fn try_into(self) -> io::Result { BlockHash::from_slice(&self.0).map_err(|_| - std::io::Error::new(std::io::ErrorKind::InvalidData, "bad block hash length") + io::Error::new(io::ErrorKind::InvalidData, "bad block hash length") ) } } @@ -58,22 +59,22 @@ impl TryInto for BinaryResponse { /// Converts a JSON value into block header data. The JSON value may be an object representing a /// block header or an array of such objects. In the latter case, the first object is converted. impl TryInto for JsonResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result { + fn try_into(self) -> io::Result { let header = match self.0 { serde_json::Value::Array(mut array) if !array.is_empty() => array.drain(..).next().unwrap(), serde_json::Value::Object(_) => self.0, - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "unexpected JSON type")), + _ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unexpected JSON type")), }; if !header.is_object() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON object")); + return Err(io::Error::new(io::ErrorKind::InvalidData, "expected JSON object")); } // Add an empty previousblockhash for the genesis block. match header.try_into() { - Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid header data")), + Err(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "invalid header data")), Ok(header) => Ok(header), } } @@ -110,15 +111,15 @@ impl TryFrom for BlockHeaderData { /// Converts a JSON value into a block. Assumes the block is hex-encoded in a JSON string. impl TryInto for JsonResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result { + fn try_into(self) -> io::Result { match self.0.as_str() { - None => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")), + None => Err(io::Error::new(io::ErrorKind::InvalidData, "expected JSON string")), Some(hex_data) => match Vec::::from_hex(hex_data) { - Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), + Err(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "invalid hex data")), Ok(block_data) => match encode::deserialize(&block_data) { - Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid block data")), + Err(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "invalid block data")), Ok(block) => Ok(block), }, }, @@ -128,31 +129,31 @@ impl TryInto for JsonResponse { /// Converts a JSON value into the best block hash and optional height. impl TryInto<(BlockHash, Option)> for JsonResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result<(BlockHash, Option)> { + fn try_into(self) -> io::Result<(BlockHash, Option)> { if !self.0.is_object() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON object")); + return Err(io::Error::new(io::ErrorKind::InvalidData, "expected JSON object")); } let hash = match &self.0["bestblockhash"] { serde_json::Value::String(hex_data) => match BlockHash::from_str(&hex_data) { - Err(_) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), + Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid hex data")), Ok(block_hash) => block_hash, }, - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")), + _ => return Err(io::Error::new(io::ErrorKind::InvalidData, "expected JSON string")), }; let height = match &self.0["blocks"] { serde_json::Value::Null => None, serde_json::Value::Number(height) => match height.as_u64() { - None => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid height")), + None => return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid height")), Some(height) => match height.try_into() { - Err(_) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid height")), + Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid height")), Ok(height) => Some(height), } }, - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON number")), + _ => return Err(io::Error::new(io::ErrorKind::InvalidData, "expected JSON number")), }; Ok((hash, height)) @@ -160,18 +161,18 @@ impl TryInto<(BlockHash, Option)> for JsonResponse { } impl TryInto for JsonResponse { - type Error = std::io::Error; - fn try_into(self) -> std::io::Result { - let hex_data = self.0.as_str().ok_or(Self::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string" ))?; - Txid::from_str(hex_data).map_err(|err|Self::Error::new(std::io::ErrorKind::InvalidData, err.to_string() )) + type Error = io::Error; + fn try_into(self) -> io::Result { + let hex_data = self.0.as_str().ok_or(io::Error::new(io::ErrorKind::InvalidData, "expected JSON string" ))?; + Txid::from_str(hex_data).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err.to_string() )) } } /// Converts a JSON value into a transaction. WATCH OUT! this cannot be used for zero-input transactions /// (e.g. createrawtransaction). See impl TryInto for JsonResponse { - type Error = std::io::Error; - fn try_into(self) -> std::io::Result { + type Error = io::Error; + fn try_into(self) -> io::Result { let hex_tx = if self.0.is_object() { // result is json encoded match &self.0["hex"] { @@ -185,8 +186,8 @@ impl TryInto for JsonResponse { _ => "Unknown error", }; - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, + return Err(io::Error::new( + io::ErrorKind::InvalidData, format!("transaction couldn't be signed. {}", reason), )); } else { @@ -196,34 +197,40 @@ impl TryInto for JsonResponse { // result is a complete transaction (e.g. getrawtranaction verbose) _ => hex_data, }, - _ => return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "expected JSON string", - )), + _ => { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "expected JSON string", + )); + } } } else { // result is plain text (e.g. getrawtransaction no verbose) match self.0.as_str() { Some(hex_tx) => hex_tx, None => { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, + return Err(io::Error::new( + io::ErrorKind::InvalidData, "expected JSON string", - )) + )); } } }; match Vec::::from_hex(hex_tx) { - Err(_) => Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "invalid hex data", - )), + Err(_) => { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "invalid hex data", + )) + } Ok(tx_data) => match encode::deserialize(&tx_data) { - Err(_) => Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "invalid transaction", - )), + Err(_) => { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "invalid transaction", + )) + } Ok(tx) => Ok(tx), }, } @@ -231,15 +238,15 @@ impl TryInto for JsonResponse { } impl TryInto for JsonResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result { + fn try_into(self) -> io::Result { match self.0.as_str() { - None => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")), + None => Err(io::Error::new(io::ErrorKind::InvalidData, "expected JSON string")), Some(hex_data) if hex_data.len() != 64 => - Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hash length")), + Err(io::Error::new(io::ErrorKind::InvalidData, "invalid hash length")), Some(hex_data) => BlockHash::from_str(hex_data) - .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid hex data")), } } } @@ -254,17 +261,20 @@ pub(crate) struct GetUtxosResponse { #[cfg(feature = "rest-client")] impl TryInto for JsonResponse { - type Error = std::io::Error; + type Error = io::Error; - fn try_into(self) -> std::io::Result { + fn try_into(self) -> io::Result { + let obj_err = || io::Error::new(io::ErrorKind::InvalidData, "expected an object"); + let bitmap_err = || io::Error::new(io::ErrorKind::InvalidData, "missing bitmap field"); + let bitstr_err = || io::Error::new(io::ErrorKind::InvalidData, "bitmap should be an str"); let bitmap_str = - self.0.as_object().ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected an object"))? - .get("bitmap").ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "missing bitmap field"))? - .as_str().ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "bitmap should be an str"))?; + self.0.as_object().ok_or_else(obj_err)? + .get("bitmap").ok_or_else(bitmap_err)? + .as_str().ok_or_else(bitstr_err)?; let mut hit_bitmap_nonempty = false; for c in bitmap_str.chars() { if c < '0' || c > '9' { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid byte")); + return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid byte")); } if c > '0' { hit_bitmap_nonempty = true; } } @@ -304,7 +314,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!(42)); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "unexpected JSON type"); }, Ok(_) => panic!("Expected error"), @@ -316,7 +326,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!([42])); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON object"); }, Ok(_) => panic!("Expected error"), @@ -335,7 +345,7 @@ pub(crate) mod tests { match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid header data"); }, Ok(_) => panic!("Expected error"), @@ -354,7 +364,7 @@ pub(crate) mod tests { match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid header data"); }, Ok(_) => panic!("Expected error"), @@ -449,7 +459,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!({ "result": "foo" })); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); }, Ok(_) => panic!("Expected error"), @@ -461,7 +471,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("foobar")); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid hex data"); }, Ok(_) => panic!("Expected error"), @@ -473,7 +483,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("abcd")); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid block data"); }, Ok(_) => panic!("Expected error"), @@ -495,7 +505,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("foo")); match TryInto::<(BlockHash, Option)>::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON object"); }, Ok(_) => panic!("Expected error"), @@ -507,7 +517,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!({ "bestblockhash": 42 })); match TryInto::<(BlockHash, Option)>::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); }, Ok(_) => panic!("Expected error"), @@ -519,7 +529,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!({ "bestblockhash": "foobar"} )); match TryInto::<(BlockHash, Option)>::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid hex data"); }, Ok(_) => panic!("Expected error"), @@ -550,7 +560,7 @@ pub(crate) mod tests { })); match TryInto::<(BlockHash, Option)>::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON number"); }, Ok(_) => panic!("Expected error"), @@ -566,7 +576,7 @@ pub(crate) mod tests { })); match TryInto::<(BlockHash, Option)>::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid height"); }, Ok(_) => panic!("Expected error"), @@ -594,7 +604,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!({ "result": "foo" })); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); } Ok(_) => panic!("Expected error"), @@ -606,7 +616,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("foobar")); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "bad hex string length 6 (expected 64)"); } Ok(_) => panic!("Expected error"), @@ -618,7 +628,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("abcd")); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "bad hex string length 4 (expected 64)"); } Ok(_) => panic!("Expected error"), @@ -641,7 +651,7 @@ pub(crate) mod tests { {"error": "", "id": "770", "result": "7934f775149929a8b742487129a7c3a535dfb612f0b726cc67bc10bc2628f906"} ); - let r: std::io::Result = JsonResponse(rpc_response.get_mut("result").unwrap().take()) + let r: io::Result = JsonResponse(rpc_response.get_mut("result").unwrap().take()) .try_into(); assert_eq!( r.unwrap().to_string(), @@ -661,7 +671,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("foobar")); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid hex data"); } Ok(_) => panic!("Expected error"), @@ -673,7 +683,7 @@ pub(crate) mod tests { let response = JsonResponse(Value::Number(Number::from_f64(1.0).unwrap())); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); } Ok(_) => panic!("Expected error"), @@ -685,7 +695,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!("abcd")); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid transaction"); } Ok(_) => panic!("Expected error"), @@ -721,7 +731,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!({ "error": "foo" })); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert_eq!( e.get_ref().unwrap().to_string(), "expected JSON string" @@ -736,7 +746,7 @@ pub(crate) mod tests { let response = JsonResponse(serde_json::json!({ "hex": "foo", "complete": false })); match TryInto::::try_into(response) { Err(e) => { - assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); + assert_eq!(e.kind(), io::ErrorKind::InvalidData); assert!( e.get_ref().unwrap().to_string().contains( "transaction couldn't be signed") -- 2.39.5