Json codec for quote protocol

A `RequestResponseCodec` for pull-based protocols where the response is encoded using JSON.
This was added to more properly express the behavior of the quote protocol, where the dialer
doesn't send any message and expects the listener to directly send the response.

Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
pull/422/head
Daniel Karzel 3 years ago
parent f70e2aa8d6
commit c1e993deb2
No known key found for this signature in database
GPG Key ID: 30C3FC2E438ADB6E

@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow multiple concurrent swaps with the same peer on the ASB.
This is a breaking change because the swap ID is now agreed upon between CLI and ASB during swap setup.
Resuming swaps started prior to this change can result in unexpected behaviour.
- Quote protocol returns JSON encoded data instead of CBOR.
This is a breaking change in the protocol handling, old CLI versions will not be able to process quote requests of ASBs running this version.
### Added

@ -2,6 +2,7 @@ mod impl_from_rr_event;
pub mod cbor_request_response;
pub mod encrypted_signature;
pub mod json_pull_codec;
pub mod quote;
pub mod redial;
pub mod spot_price;

@ -0,0 +1,99 @@
use async_trait::async_trait;
use futures::prelude::*;
use libp2p::core::upgrade;
use libp2p::request_response::{ProtocolName, RequestResponseCodec};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::fmt::Debug;
use std::io;
use std::marker::PhantomData;
/// Message receive buffer.
pub const BUF_SIZE: usize = 1024 * 1024;
/// A [`RequestResponseCodec`] for pull-based protocols where the response is
/// encoded using JSON.
///
/// A pull-based protocol is a protocol where the dialer doesn't send any
/// message and expects the listener to directly send the response as the
/// substream is opened.
#[derive(Clone, Copy, Debug)]
pub struct JsonPullCodec<P, Res> {
phantom: PhantomData<(P, Res)>,
}
impl<P, Res> Default for JsonPullCodec<P, Res> {
fn default() -> Self {
Self {
phantom: PhantomData::default(),
}
}
}
#[async_trait]
impl<P, Res> RequestResponseCodec for JsonPullCodec<P, Res>
where
P: ProtocolName + Send + Sync + Clone,
Res: DeserializeOwned + Serialize + Send,
{
type Protocol = P;
type Request = ();
type Response = Res;
async fn read_request<T>(&mut self, _: &Self::Protocol, _: &mut T) -> io::Result<Self::Request>
where
T: AsyncRead + Unpin + Send,
{
Ok(())
}
async fn read_response<T>(
&mut self,
_: &Self::Protocol,
io: &mut T,
) -> io::Result<Self::Response>
where
T: AsyncRead + Unpin + Send,
{
let message = upgrade::read_one(io, BUF_SIZE)
.await
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let mut de = serde_json::Deserializer::from_slice(&message);
let msg = Res::deserialize(&mut de).map_err(|e| {
tracing::debug!("serde read_response error: {:?}", e);
io::Error::new(io::ErrorKind::InvalidData, e)
})?;
Ok(msg)
}
async fn write_request<T>(
&mut self,
_: &Self::Protocol,
_: &mut T,
_: Self::Request,
) -> io::Result<()>
where
T: AsyncWrite + Unpin + Send,
{
Ok(())
}
async fn write_response<T>(
&mut self,
_: &Self::Protocol,
io: &mut T,
res: Self::Response,
) -> io::Result<()>
where
T: AsyncWrite + Unpin + Send,
{
let bytes = serde_json::to_vec(&res).map_err(|e| {
tracing::debug!("serde write_response error: {:?}", e);
io::Error::new(io::ErrorKind::InvalidData, e)
})?;
upgrade::write_one(io, &bytes).await?;
Ok(())
}
}

@ -1,5 +1,5 @@
use crate::bitcoin;
use crate::network::cbor_request_response::CborCodec;
use crate::network::json_pull_codec::JsonPullCodec;
use crate::protocol::{alice, bob};
use libp2p::core::ProtocolName;
use libp2p::request_response::{
@ -13,7 +13,7 @@ const PROTOCOL: &str = "/comit/xmr/btc/bid-quote/1.0.0";
type OutEvent = RequestResponseEvent<(), BidQuote>;
type Message = RequestResponseMessage<(), BidQuote>;
pub type Behaviour = RequestResponse<CborCodec<BidQuoteProtocol, (), BidQuote>>;
pub type Behaviour = RequestResponse<JsonPullCodec<BidQuoteProtocol, BidQuote>>;
#[derive(Debug, Clone, Copy, Default)]
pub struct BidQuoteProtocol;
@ -40,7 +40,7 @@ pub struct BidQuote {
/// Alice only supports inbound connections, i.e. handing out quotes.
pub fn alice() -> Behaviour {
Behaviour::new(
CborCodec::default(),
JsonPullCodec::default(),
vec![(BidQuoteProtocol, ProtocolSupport::Inbound)],
RequestResponseConfig::default(),
)
@ -51,7 +51,7 @@ pub fn alice() -> Behaviour {
/// Bob only supports outbound connections, i.e. requesting quotes.
pub fn bob() -> Behaviour {
Behaviour::new(
CborCodec::default(),
JsonPullCodec::default(),
vec![(BidQuoteProtocol, ProtocolSupport::Outbound)],
RequestResponseConfig::default(),
)

Loading…
Cancel
Save