From f9126c7e0250550799aeb9e8036a753f1a3843d8 Mon Sep 17 00:00:00 2001 From: Daniel Karzel Date: Mon, 30 Mar 2020 11:24:29 +1100 Subject: [PATCH] Replace H256 and H160 with own Hash and Address --- cnd/src/btsieve/ethereum.rs | 12 +- cnd/src/btsieve/ethereum/web3_connector.rs | 6 +- cnd/src/comit_api.rs | 2 +- cnd/src/ethereum.rs | 204 ++++++++++++++++-- cnd/src/http_api.rs | 8 +- .../http_api/routes/rfc003/handlers/action.rs | 9 +- .../routes/rfc003/handlers/post_swap.rs | 2 +- cnd/src/network.rs | 16 +- .../network/protocols/ethereum_identity.rs | 2 +- cnd/src/quickcheck.rs | 20 +- cnd/src/swap_protocols/rfc003/ethereum.rs | 12 +- .../rfc003/ethereum/htlc_events.rs | 8 +- cnd/tests/ethereum_helper/connector_mock.rs | 12 +- libp2p-comit/src/frame/header.rs | 6 +- libp2p-comit/src/frame/request.rs | 2 +- libp2p-comit/src/substream/inbound.rs | 34 +-- libp2p-comit/src/substream/outbound.rs | 3 +- 17 files changed, 269 insertions(+), 89 deletions(-) diff --git a/cnd/src/btsieve/ethereum.rs b/cnd/src/btsieve/ethereum.rs index 92823d186b..2cf687cdd0 100644 --- a/cnd/src/btsieve/ethereum.rs +++ b/cnd/src/btsieve/ethereum.rs @@ -6,14 +6,14 @@ use crate::{ btsieve::{ find_relevant_blocks, BlockByHash, BlockHash, LatestBlock, Predates, PreviousBlockHash, }, - ethereum::{Address, Bytes, Input, Log, Transaction, TransactionReceipt, H256, U256}, + ethereum::{Address, Bytes, Input, Log, Transaction, TransactionReceipt, U256}, }; use anyhow; use async_trait::async_trait; use chrono::NaiveDateTime; use genawaiter::{sync::Gen, GeneratorState}; -type Hash = H256; +type Hash = crate::ethereum::Hash; type Block = crate::ethereum::Block; #[async_trait] @@ -24,7 +24,7 @@ pub trait ReceiptByHash: Send + Sync + 'static { impl BlockHash for Block { type BlockHash = Hash; - fn block_hash(&self) -> H256 { + fn block_hash(&self) -> Hash { self.hash .expect("Connector returned latest block with null hash") } @@ -33,7 +33,7 @@ impl BlockHash for Block { impl PreviousBlockHash for Block { type BlockHash = Hash; - fn previous_block_hash(&self) -> H256 { + fn previous_block_hash(&self) -> Hash { self.parent_hash } } @@ -174,7 +174,7 @@ where topic.as_ref().map_or(true, |topic| { block .logs_bloom - .contains_input(Input::Raw(topic.0.as_ref())) + .contains_input(Input::Raw(&topic.0.as_bytes())) }) }); if !maybe_contains_transaction { @@ -227,7 +227,7 @@ impl Predates for Block { #[derive(Clone, Copy, Default, Eq, PartialEq, serde::Serialize, serdebug::SerDebug)] #[serde(transparent)] -pub struct Topic(pub H256); +pub struct Topic(pub Hash); /// Event works similar to web3 filters: /// https://web3js.readthedocs.io/en/1.0/web3-eth-subscribe.html?highlight=filter#subscribe-logs diff --git a/cnd/src/btsieve/ethereum/web3_connector.rs b/cnd/src/btsieve/ethereum/web3_connector.rs index ad1b3e44f8..b38431c712 100644 --- a/cnd/src/btsieve/ethereum/web3_connector.rs +++ b/cnd/src/btsieve/ethereum/web3_connector.rs @@ -1,7 +1,7 @@ use crate::{ btsieve::{ethereum::ReceiptByHash, BlockByHash, LatestBlock}, config::validation::FetchNetworkId, - ethereum::{TransactionReceipt, H256}, + ethereum::{Hash, TransactionReceipt}, jsonrpc, swap_protocols::ledger::ethereum::ChainId, }; @@ -45,7 +45,7 @@ impl LatestBlock for Web3Connector { #[async_trait] impl BlockByHash for Web3Connector { type Block = crate::ethereum::Block; - type BlockHash = crate::ethereum::H256; + type BlockHash = crate::ethereum::Hash; async fn block_by_hash(&self, block_hash: Self::BlockHash) -> anyhow::Result { let block = self @@ -64,7 +64,7 @@ impl BlockByHash for Web3Connector { #[async_trait] impl ReceiptByHash for Web3Connector { - async fn receipt_by_hash(&self, transaction_hash: H256) -> anyhow::Result { + async fn receipt_by_hash(&self, transaction_hash: Hash) -> anyhow::Result { let receipt = self .client .send(jsonrpc::Request::new("eth_getTransactionReceipt", vec![ diff --git a/cnd/src/comit_api.rs b/cnd/src/comit_api.rs index 676e4ec5af..7e102f4b28 100644 --- a/cnd/src/comit_api.rs +++ b/cnd/src/comit_api.rs @@ -168,7 +168,7 @@ mod tests { #[test] fn erc20_quantity_to_header() -> Result<(), serde_json::Error> { let quantity = asset::Erc20::new( - Address::zero(), + Address::from([0u8; 20]), asset::Erc20Quantity::from_wei(U256::from(100_000_000_000_000u64)), ); let header = AssetKind::from(quantity).to_header()?; diff --git a/cnd/src/ethereum.rs b/cnd/src/ethereum.rs index 7177f0098f..b143122f68 100644 --- a/cnd/src/ethereum.rs +++ b/cnd/src/ethereum.rs @@ -1,22 +1,140 @@ #![warn(unused_extern_crates, missing_debug_implementations, rust_2018_idioms)] #![forbid(unsafe_code)] +use bitcoin::hashes::core::{fmt::Formatter, str::FromStr}; +use core::fmt; pub use ethbloom::{Bloom as H2048, Input}; -pub use primitive_types::{H160, H256, U128, U256}; +use hex::FromHexError; +pub use primitive_types::U256; use serde::{Deserialize, Serialize}; use serde_hex::{CompactPfx, SerHex, SerHexSeq, StrictPfx}; - -pub type Address = H160; +use std::fmt::Display; #[derive(Debug, Default, Copy, Clone, PartialEq, Deserialize)] pub struct H64(#[serde(with = "SerHex::")] [u8; 8]); +#[derive( + Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, +)] +pub struct Address(#[serde(with = "SerHex::")] [u8; 20]); + +impl Address { + pub fn from_slice(src: &[u8]) -> Self { + let mut address = Address([0u8; 20]); + address.0.copy_from_slice(src); + address + } +} + +impl From<[u8; 20]> for Address { + fn from(bytes: [u8; 20]) -> Self { + Address(bytes) + } +} + +impl From
for [u8; 20] { + fn from(s: Address) -> Self { + s.0 + } +} + +impl FromStr for Address { + type Err = FromHexError; + + fn from_str(s: &str) -> Result { + hex::decode(s).map(|v| Address::from_slice(v.as_slice())) + } +} + +impl From
for Hash { + fn from(address: Address) -> Self { + let mut h256 = Hash([0u8; 32]); + h256.0[(32 - 20)..32].copy_from_slice(&address.0); + h256 + } +} + +impl fmt::LowerHex for Address { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "0x")?; + } + for i in &self.0[..] { + write!(f, "{:02x}", i)?; + } + Ok(()) + } +} + +#[derive( + Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, +)] +pub struct Hash(#[serde(with = "SerHex::")] [u8; 32]); + +impl From<[u8; 32]> for Hash { + fn from(bytes: [u8; 32]) -> Self { + Hash(bytes) + } +} + +impl From for [u8; 32] { + fn from(s: Hash) -> Self { + s.0 + } +} + +impl Hash { + pub fn from_slice(src: &[u8]) -> Self { + let mut h256 = Hash([0u8; 32]); + h256.0.copy_from_slice(src); + h256 + } + + pub fn as_bytes(&self) -> &[u8] { + &self.0 + } +} + +impl FromStr for Hash { + type Err = FromHexError; + + fn from_str(s: &str) -> Result { + hex::decode(s).map(|v| Hash::from_slice(v.as_slice())) + } +} + +impl fmt::LowerHex for Hash { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "0x")?; + } + for i in &self.0[..] { + write!(f, "{:02x}", i)?; + } + Ok(()) + } +} + +impl Display for Hash { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "0x")?; + for i in &self.0[0..2] { + write!(f, "{:02x}", i)?; + } + write!(f, "…")?; + for i in &self.0[32 - 2..32] { + write!(f, "{:02x}", i)?; + } + Ok(()) + } +} + /// "Receipt" of an executed transaction: details of its execution. #[derive(Debug, Default, Clone, PartialEq, Deserialize)] pub struct TransactionReceipt { /// Contract address created, or `None` if not a deployment. #[serde(rename = "contractAddress")] - pub contract_address: Option, + pub contract_address: Option
, /// Logs generated within this transaction. pub logs: Vec, /// Status: either 1 (success) or 0 (failure). @@ -34,9 +152,9 @@ impl TransactionReceipt { #[derive(Debug, Default, Clone, PartialEq, Deserialize)] pub struct Transaction { /// Hash - pub hash: H256, + pub hash: Hash, /// Recipient (None when contract creation) - pub to: Option, + pub to: Option
, /// Transfered value pub value: U256, /// Input data @@ -47,9 +165,9 @@ pub struct Transaction { #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct Log { /// H160 - pub address: H160, + pub address: Address, /// Topics - pub topics: Vec, + pub topics: Vec, /// Data pub data: Bytes, } @@ -60,10 +178,10 @@ pub struct Log { #[derive(Debug, Default, Clone, PartialEq, Deserialize)] pub struct Block { /// Hash of the block - pub hash: Option, + pub hash: Option, /// Hash of the parent #[serde(rename = "parentHash")] - pub parent_hash: H256, + pub parent_hash: Hash, /// Logs bloom #[serde(rename = "logsBloom")] pub logs_bloom: H2048, @@ -85,8 +203,70 @@ impl>> From for Bytes { #[cfg(test)] mod tests { - use super::Log; - use crate::ethereum::TransactionReceipt; + use super::*; + + #[test] + fn deserialise_address() { + let json = + serde_json::Value::String("0xc5549e335b2786520f4c5d706c76c9ee69d0a028".to_owned()); + let _: Address = Address::deserialize(&json).unwrap(); + } + + #[test] + fn deserialise_address_when_not_using_reference_to_deserialize_fails() { + // This is due to a bug in serde-jex, keep this test until https://github.com/fspmarshall/serde-hex/pull/8 + // is fixed. + let json = + serde_json::Value::String("0xc5549e335b2786520f4c5d706c76c9ee69d0a028".to_owned()); + + let deserialized = serde_json::from_value::
(json); + matches!(deserialized, Err(_)); + } + + #[test] + fn from_string_address() { + let json = + serde_json::Value::String("0xc5549e335b2786520f4c5d706c76c9ee69d0a028".to_owned()); + let deserialized: Address = Address::deserialize(&json).unwrap(); + + let from_string = Address::from_str("c5549e335b2786520f4c5d706c76c9ee69d0a028").unwrap(); + + assert_eq!(from_string, deserialized); + } + + #[test] + fn deserialise_hash() { + let json = serde_json::Value::String( + "0x3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9".to_owned(), + ); + let _: Hash = Hash::deserialize(&json).unwrap(); + } + + #[test] + fn deserialise_hash_when_not_using_reference_to_deserialize_fails() { + // This is due to a bug in serde-jex, keep this test until https://github.com/fspmarshall/serde-hex/pull/8 + // is fixed. + let json = serde_json::Value::String( + "0x3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9".to_owned(), + ); + + let deserialized = serde_json::from_value::(json); + matches!(deserialized, Err(_)); + } + + #[test] + fn from_string_hash() { + let json = serde_json::Value::String( + "0x3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9".to_owned(), + ); + let deserialized: Hash = Hash::deserialize(&json).unwrap(); + + let from_string = + Hash::from_str("3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9") + .unwrap(); + + assert_eq!(from_string, deserialized); + } #[test] fn deserialise_log() { diff --git a/cnd/src/http_api.rs b/cnd/src/http_api.rs index d237df86ac..81c1e8a41b 100644 --- a/cnd/src/http_api.rs +++ b/cnd/src/http_api.rs @@ -97,7 +97,7 @@ impl Serialize for Http { } impl_serialize_type_with_fields!(htlc_location::Bitcoin { "txid" => txid, "vout" => vout }); -impl_serialize_http!(crate::ethereum::H160); +impl_serialize_http!(crate::ethereum::Address); impl_serialize_http!(SwapId); impl Serialize for Http { @@ -489,7 +489,7 @@ mod tests { asset, asset::ethereum::FromWei, bitcoin::PublicKey, - ethereum::{H160, H256, U256}, + ethereum::{Address, Hash, U256}, http_api::{Http, HttpAsset, HttpLedger}, swap_protocols::{ ledger::{bitcoin, ethereum, Ethereum}, @@ -591,7 +591,7 @@ mod tests { output: vec![], }; let ethereum_tx = transaction::Ethereum { - hash: H256::repeat_byte(1), + hash: Hash::from([1u8; 32]), ..transaction::Ethereum::default() }; @@ -618,7 +618,7 @@ mod tests { .parse() .unwrap(); - let ethereum_identity = H160::repeat_byte(7); + let ethereum_identity = Address::from([7u8; 20]); let bitcoin_identity = Http(bitcoin_identity); let ethereum_identity = Http(ethereum_identity); diff --git a/cnd/src/http_api/routes/rfc003/handlers/action.rs b/cnd/src/http_api/routes/rfc003/handlers/action.rs index d4262c2dcf..0beb9f24d1 100644 --- a/cnd/src/http_api/routes/rfc003/handlers/action.rs +++ b/cnd/src/http_api/routes/rfc003/handlers/action.rs @@ -26,7 +26,7 @@ use crate::{ }; use anyhow::Context; use libp2p_comit::frame::Response; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::{ fmt::{self, Debug, Display}, string::ToString, @@ -75,8 +75,8 @@ pub async fn handle_action( match action { Action::Accept(_) => { - let body = serde_json::from_value::(body) - .context("failed to deserialize accept body")?; + let body = + AcceptBody::deserialize(&body).context("failed to deserialize accept body")?; let channel = dependencies .pending_request_for(swap_id) @@ -112,7 +112,8 @@ pub async fn handle_action( Ok(ActionResponseBody::None) } Action::Decline(_) => { - let body = serde_json::from_value::(body)?; + let body = DeclineBody::deserialize(&body) + .context("failed to deserialize decline body")?; let channel = dependencies .pending_request_for(swap_id) diff --git a/cnd/src/http_api/routes/rfc003/handlers/post_swap.rs b/cnd/src/http_api/routes/rfc003/handlers/post_swap.rs index f222548589..85a7d24a33 100644 --- a/cnd/src/http_api/routes/rfc003/handlers/post_swap.rs +++ b/cnd/src/http_api/routes/rfc003/handlers/post_swap.rs @@ -128,7 +128,7 @@ pub async fn handle_post_swap( let seed = dependencies.derive_swap_seed(id); let secret_hash = seed.derive_secret().hash(); - let body = serde_json::from_value(body)?; + let body = SwapRequestBody::deserialize(&body)?; match body { SwapRequestBody { diff --git a/cnd/src/network.rs b/cnd/src/network.rs index f8e99b4ed1..65b6da2181 100644 --- a/cnd/src/network.rs +++ b/cnd/src/network.rs @@ -50,7 +50,7 @@ use libp2p_comit::{ handler::{ComitHandler, ProtocolInEvent, ProtocolOutEvent}, BehaviourOutEvent, Comit, PendingInboundRequest, }; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{ collections::{HashMap, HashSet}, convert::{TryFrom, TryInto}, @@ -1012,9 +1012,10 @@ impl SendRequest for Swarm { match decision { Some(Decision::Accepted) => { - match serde_json::from_value::>( - response.body().clone(), - ) { + let accept_body = + rfc003::messages::AcceptResponseBody::deserialize(response.body()); + + match accept_body { Ok(body) => Ok(Ok(rfc003::Accept { swap_id: id, beta_ledger_refund_identity: body.beta_ledger_refund_identity, @@ -1025,9 +1026,10 @@ impl SendRequest for Swarm { } Some(Decision::Declined) => { - match serde_json::from_value::( - response.body().clone(), - ) { + let decline_body = + rfc003::messages::DeclineResponseBody::deserialize(response.body()); + + match decline_body { Ok(body) => Ok(Err(rfc003::Decline { swap_id: id, reason: body.reason, diff --git a/cnd/src/network/protocols/ethereum_identity.rs b/cnd/src/network/protocols/ethereum_identity.rs index eb37b59f38..fc1c629c25 100644 --- a/cnd/src/network/protocols/ethereum_identity.rs +++ b/cnd/src/network/protocols/ethereum_identity.rs @@ -16,7 +16,7 @@ impl Message { pub fn new(swap_id: SwapId, address: identity::Ethereum) -> Self { Self { swap_id, - address: address.0, + address: address.into(), } } } diff --git a/cnd/src/quickcheck.rs b/cnd/src/quickcheck.rs index d996553e5e..5071f34e86 100644 --- a/cnd/src/quickcheck.rs +++ b/cnd/src/quickcheck.rs @@ -2,7 +2,7 @@ use crate::{ asset, asset::ethereum::FromWei, db::Swap, - ethereum::Bytes, + ethereum::{Address, Bytes}, identity, swap_protocols::{ ledger, @@ -167,31 +167,23 @@ impl Arbitrary for Quickcheck { fn arbitrary(g: &mut G) -> Self { let bytes = *Quickcheck::<[u8; 20]>::arbitrary(g); - Quickcheck(identity::Ethereum::from(bytes)) + Quickcheck(Address::from(bytes)) } } -impl Arbitrary for Quickcheck { - fn arbitrary(g: &mut G) -> Self { - let bytes = *Quickcheck::<[u8; 16]>::arbitrary(g); - - Quickcheck(crate::ethereum::U128::from(&bytes)) - } -} - -impl Arbitrary for Quickcheck { +impl Arbitrary for Quickcheck { fn arbitrary(g: &mut G) -> Self { let bytes = *Quickcheck::<[u8; 32]>::arbitrary(g); - Quickcheck(crate::ethereum::H256::from(&bytes)) + Quickcheck(crate::ethereum::Hash::from(bytes)) } } impl Arbitrary for Quickcheck { fn arbitrary(g: &mut G) -> Self { Quickcheck(transaction::Ethereum { - hash: *Quickcheck::::arbitrary(g), - to: Option::>::arbitrary(g).map(|i| i.0), + hash: *Quickcheck::::arbitrary(g), + to: Option::>::arbitrary(g).map(|i| i.0), value: *Quickcheck::::arbitrary(g), input: Bytes(Arbitrary::arbitrary(g)), }) diff --git a/cnd/src/swap_protocols/rfc003/ethereum.rs b/cnd/src/swap_protocols/rfc003/ethereum.rs index c53c9e9fb1..bbfe3fa46a 100644 --- a/cnd/src/swap_protocols/rfc003/ethereum.rs +++ b/cnd/src/swap_protocols/rfc003/ethereum.rs @@ -10,8 +10,10 @@ use blockchain_contracts::ethereum::rfc003::{erc20_htlc::Erc20Htlc, ether_htlc:: impl From> for EtherHtlc { fn from(htlc_params: HtlcParams) -> Self { - let refund_address = blockchain_contracts::ethereum::Address(htlc_params.refund_identity.0); - let redeem_address = blockchain_contracts::ethereum::Address(htlc_params.redeem_identity.0); + let refund_address = + blockchain_contracts::ethereum::Address(htlc_params.refund_identity.into()); + let redeem_address = + blockchain_contracts::ethereum::Address(htlc_params.redeem_identity.into()); EtherHtlc::new( htlc_params.expiry.into(), @@ -30,8 +32,10 @@ impl HtlcParams { impl From> for Erc20Htlc { fn from(htlc_params: HtlcParams) -> Self { - let refund_address = blockchain_contracts::ethereum::Address(htlc_params.refund_identity.0); - let redeem_address = blockchain_contracts::ethereum::Address(htlc_params.redeem_identity.0); + let refund_address = + blockchain_contracts::ethereum::Address(htlc_params.refund_identity.into()); + let redeem_address = + blockchain_contracts::ethereum::Address(htlc_params.redeem_identity.into()); let token_contract_address = blockchain_contracts::ethereum::Address(htlc_params.asset.token_contract.into()); diff --git a/cnd/src/swap_protocols/rfc003/ethereum/htlc_events.rs b/cnd/src/swap_protocols/rfc003/ethereum/htlc_events.rs index 63bd684da1..cb866c2aa9 100644 --- a/cnd/src/swap_protocols/rfc003/ethereum/htlc_events.rs +++ b/cnd/src/swap_protocols/rfc003/ethereum/htlc_events.rs @@ -4,7 +4,7 @@ use crate::{ btsieve::ethereum::{ watch_for_contract_creation, watch_for_event, Cache, Event, Topic, Web3Connector, }, - ethereum::{H256, U256}, + ethereum::{Hash, U256}, htlc_location, identity, swap_protocols::{ ledger::Ethereum, @@ -24,10 +24,10 @@ use std::cmp::Ordering; use tracing_futures::Instrument; lazy_static::lazy_static! { - static ref REDEEM_LOG_MSG: H256 = blockchain_contracts::ethereum::rfc003::REDEEMED_LOG_MSG.parse().expect("to be valid hex"); - static ref REFUND_LOG_MSG: H256 = blockchain_contracts::ethereum::rfc003::REFUNDED_LOG_MSG.parse().expect("to be valid hex"); + static ref REDEEM_LOG_MSG: Hash = blockchain_contracts::ethereum::rfc003::REDEEMED_LOG_MSG.parse().expect("to be valid hex"); + static ref REFUND_LOG_MSG: Hash = blockchain_contracts::ethereum::rfc003::REFUNDED_LOG_MSG.parse().expect("to be valid hex"); /// keccak('Transfer(address,address,uint256)') - static ref TRANSFER_LOG_MSG: H256 = "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".parse().expect("to be valid hex"); + static ref TRANSFER_LOG_MSG: Hash = "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".parse().expect("to be valid hex"); } #[async_trait::async_trait] diff --git a/cnd/tests/ethereum_helper/connector_mock.rs b/cnd/tests/ethereum_helper/connector_mock.rs index f47a4daa2d..2e39837dd4 100644 --- a/cnd/tests/ethereum_helper/connector_mock.rs +++ b/cnd/tests/ethereum_helper/connector_mock.rs @@ -2,15 +2,15 @@ use anyhow::Context; use async_trait::async_trait; use cnd::{ btsieve::{ethereum::ReceiptByHash, BlockByHash, LatestBlock}, - ethereum::{Block, TransactionReceipt, H256}, + ethereum::{Block, Hash, TransactionReceipt}, }; use futures::{stream::BoxStream, StreamExt}; use std::{collections::HashMap, time::Duration}; use tokio::{stream, sync::Mutex, time::throttle}; pub struct EthereumConnectorMock { - all_blocks: HashMap, - receipts: HashMap, + all_blocks: HashMap, + receipts: HashMap, latest_blocks: Mutex>, } @@ -18,7 +18,7 @@ impl EthereumConnectorMock { pub fn new( latest_blocks: Vec, all_blocks: Vec, - receipts: Vec<(H256, TransactionReceipt)>, + receipts: Vec<(Hash, TransactionReceipt)>, ) -> Self { let all_blocks = all_blocks .into_iter() @@ -61,7 +61,7 @@ impl LatestBlock for EthereumConnectorMock { #[async_trait] impl BlockByHash for EthereumConnectorMock { type Block = Block; - type BlockHash = H256; + type BlockHash = Hash; async fn block_by_hash(&self, block_hash: Self::BlockHash) -> anyhow::Result { self.all_blocks @@ -73,7 +73,7 @@ impl BlockByHash for EthereumConnectorMock { #[async_trait] impl ReceiptByHash for EthereumConnectorMock { - async fn receipt_by_hash(&self, transaction_hash: H256) -> anyhow::Result { + async fn receipt_by_hash(&self, transaction_hash: Hash) -> anyhow::Result { self.receipts .get(&transaction_hash) .cloned() diff --git a/libp2p-comit/src/frame/header.rs b/libp2p-comit/src/frame/header.rs index bb047ccf43..19b43f0e3b 100644 --- a/libp2p-comit/src/frame/header.rs +++ b/libp2p-comit/src/frame/header.rs @@ -72,7 +72,7 @@ impl Header { where V: DeserializeOwned, { - serde_json::from_value(self.inner.value()) + V::deserialize(&self.inner.value()) } /// Returns the parameter with the provided key converted into the type `P`. @@ -91,7 +91,7 @@ impl Header { .take_parameter(key) .unwrap_or(serde_json::Value::Null); - serde_json::from_value(parameter) + P::deserialize(¶meter) } /// Returns the parameter with the provided key converted into the type `P` @@ -105,7 +105,7 @@ impl Header { { self.inner .take_parameter(key) - .map(serde_json::from_value) + .map(|v| P::deserialize(&v)) .unwrap_or_else(|| Ok(P::default())) } diff --git a/libp2p-comit/src/frame/request.rs b/libp2p-comit/src/frame/request.rs index b3f0dd7403..8015742242 100644 --- a/libp2p-comit/src/frame/request.rs +++ b/libp2p-comit/src/frame/request.rs @@ -145,7 +145,7 @@ impl Request { where B: DeserializeOwned, { - B::deserialize(self.body) + B::deserialize(&self.body) } } diff --git a/libp2p-comit/src/substream/inbound.rs b/libp2p-comit/src/substream/inbound.rs index c3600a8089..682b2bd169 100644 --- a/libp2p-comit/src/substream/inbound.rs +++ b/libp2p-comit/src/substream/inbound.rs @@ -7,6 +7,7 @@ use crate::{ }; use futures::{channel::oneshot, task::Poll, Future, Sink, Stream}; use libp2p::swarm::ProtocolsHandlerEvent; +use serde::Deserialize; use std::{ collections::{HashMap, HashSet}, pin::Pin, @@ -52,23 +53,22 @@ impl Advance for State { WaitingMessage { mut stream } => match stream.as_mut().poll_next(cx) { Poll::Ready(Some(Ok(frame))) => match frame.kind { FrameKind::Request => { - let request = - serde_json::from_value::(frame.payload) - .map_err(handler::Error::MalformedFrame) - .and_then(|request| { - known_headers - .get(request.request_type()) - .ok_or_else(|| { - handler::Error::UnknownRequestType( - request.request_type().to_owned(), - ) - }) - .and_then(|known_headers| { - request - .ensure_no_unknown_mandatory_headers(known_headers) - .map_err(handler::Error::UnknownMandatoryHeader) - }) - }); + let request = UnvalidatedInboundRequest::deserialize(&frame.payload) + .map_err(handler::Error::MalformedFrame) + .and_then(|request| { + known_headers + .get(request.request_type()) + .ok_or_else(|| { + handler::Error::UnknownRequestType( + request.request_type().to_owned(), + ) + }) + .and_then(|known_headers| { + request + .ensure_no_unknown_mandatory_headers(known_headers) + .map_err(handler::Error::UnknownMandatoryHeader) + }) + }); match request { Ok(request) => { diff --git a/libp2p-comit/src/substream/outbound.rs b/libp2p-comit/src/substream/outbound.rs index f8164a316c..aaf4f8b569 100644 --- a/libp2p-comit/src/substream/outbound.rs +++ b/libp2p-comit/src/substream/outbound.rs @@ -7,6 +7,7 @@ use crate::{ }; use futures::{channel::oneshot, Sink, Stream}; use libp2p::swarm::ProtocolsHandlerEvent; +use serde::Deserialize; use std::{ collections::{HashMap, HashSet}, pin::Pin, @@ -85,7 +86,7 @@ impl Advance for State { } => match stream.as_mut().poll_next(cx) { Poll::Ready(Some(Ok(frame))) => { let response = match frame.kind { - FrameKind::Response => serde_json::from_value(frame.payload), + FrameKind::Response => Response::deserialize(&frame.payload), FrameKind::Request => { return Advanced::error(stream, handler::Error::UnexpectedFrame(frame)) }