Sfoglia il codice sorgente

serial: Introduce full async serialization support.

Unfortunately this duplicates the code, but it is beneficial for perf.
parazyd 3 anni fa
parent
commit
75cb654068

+ 2 - 0
Cargo.lock

@@ -1526,6 +1526,7 @@ dependencies = [
  "darkfi-derive-internal",
  "proc-macro-crate",
  "proc-macro2",
+ "quote",
  "syn 2.0.29",
 ]
 
@@ -1595,6 +1596,7 @@ dependencies = [
 name = "darkfi-serial"
 version = "0.4.1"
 dependencies = [
+ "async-trait",
  "blake3",
  "bridgetree",
  "darkfi-derive",

+ 3 - 1
src/serial/Cargo.toml

@@ -11,6 +11,7 @@ edition = "2021"
 [dependencies]
 darkfi-derive = {version = "0.4.1", path = "./derive", optional = true}
 futures-lite = {version = "1.13.0", optional = true}
+async-trait = {version = "0.1.73", optional = true}
 
 # Supported types for encoding
 blake3 = {version = "1.4.1", optional = true}
@@ -23,7 +24,8 @@ url = {version = "2.4.0", optional = true}
 default = ["derive", "semver"]
 derive = ["darkfi-derive"]
 
-async = ["futures-lite"]
+async = ["futures-lite", "async-trait", "darkfi-derive/async"]
+
 collections = []
 crypto = ["collections", "hash", "bridgetree", "pasta_curves"]
 hash = ["blake3"]

+ 656 - 0
src/serial/src/async_lib.rs

@@ -0,0 +1,656 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2023 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use std::{
+    collections::VecDeque,
+    io::{Error, ErrorKind, Result},
+};
+
+use async_trait::async_trait;
+use futures_lite::{
+    io::Cursor, AsyncRead, AsyncReadExt as FutAsyncReadExt, AsyncWrite,
+    AsyncWriteExt as FutAsyncWriteExt,
+};
+
+use crate::{endian, VarInt};
+
+/// Data which can asynchronously be encoded in a consensus-consistent way.
+#[async_trait]
+pub trait AsyncEncodable {
+    /// Asynchronously encode an object with a well-defined format.
+    /// Should only ever error if the underlying `AsyncWrite` errors.
+    /// Returns the number of bytes written on success.
+    async fn encode_async<W: AsyncWrite + Unpin + Send>(&self, w: &mut W) -> Result<usize>;
+}
+
+/// Data which can asynchronously be decoded in a consensus-consistent way.
+#[async_trait]
+pub trait AsyncDecodable: Sized {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self>;
+}
+
+/// Asynchronously encode an object into a vector.
+pub async fn serialize_async<T: AsyncEncodable + ?Sized>(data: &T) -> Vec<u8> {
+    let mut encoder = Vec::new();
+    let len = data.encode_async(&mut encoder).await.unwrap();
+    assert_eq!(len, encoder.len());
+    encoder
+}
+
+/// Asynchronously deserialize an object from a vector, but do not error if the
+/// entire vector is not consumed.
+pub async fn deserialize_async_partial<T: AsyncDecodable>(data: &[u8]) -> Result<(T, usize)> {
+    let mut decoder = Cursor::new(data);
+    let rv = AsyncDecodable::decode_async(&mut decoder).await?;
+    let consumed = decoder.position() as usize;
+
+    Ok((rv, consumed))
+}
+
+/// Asynchronously deserialize an object from a vector.
+/// Will error if said deserialization doesn't consume the entire vector.
+pub async fn deserialize_async<T: AsyncDecodable>(data: &[u8]) -> Result<T> {
+    let (rv, consumed) = deserialize_async_partial(data).await?;
+
+    // Fail if data is not consumed entirely.
+    if consumed != data.len() {
+        return Err(Error::new(ErrorKind::Other, "Data not consumed fully on deserialization"))
+    }
+
+    Ok(rv)
+}
+
+/// Extensions of `AsyncWrite` to encode data as per Bitcoin consensus.
+#[async_trait]
+pub trait AsyncWriteExt {
+    /// Output a 128-bit unsigned int
+    async fn write_u128_async(&mut self, v: u128) -> Result<()>;
+    /// Output a 64-bit unsigned int
+    async fn write_u64_async(&mut self, v: u64) -> Result<()>;
+    /// Output a 32-bit unsigned int
+    async fn write_u32_async(&mut self, v: u32) -> Result<()>;
+    /// Output a 16-bit unsigned int
+    async fn write_u16_async(&mut self, v: u16) -> Result<()>;
+    /// Output an 8-bit unsigned int
+    async fn write_u8_async(&mut self, v: u8) -> Result<()>;
+
+    /// Output a 128-bit signed int
+    async fn write_i128_async(&mut self, v: i128) -> Result<()>;
+    /// Output a 64-bit signed int
+    async fn write_i64_async(&mut self, v: i64) -> Result<()>;
+    /// Ouptut a 32-bit signed int
+    async fn write_i32_async(&mut self, v: i32) -> Result<()>;
+    /// Output a 16-bit signed int
+    async fn write_i16_async(&mut self, v: i16) -> Result<()>;
+    /// Output an 8-bit signed int
+    async fn write_i8_async(&mut self, v: i8) -> Result<()>;
+
+    /// Output a 64-bit floating point int
+    async fn write_f64_async(&mut self, v: f64) -> Result<()>;
+    /// Output a 32-bit floating point int
+    async fn write_f32_async(&mut self, v: f32) -> Result<()>;
+
+    /// Output a boolean
+    async fn write_bool_async(&mut self, v: bool) -> Result<()>;
+
+    /// Output a byte slice
+    async fn write_slice_async(&mut self, v: &[u8]) -> Result<()>;
+}
+
+/// Extensions of `AsyncRead` to decode data as per Bitcoin consensus.
+#[async_trait]
+pub trait AsyncReadExt {
+    /// Read a 128-bit unsigned int
+    async fn read_u128_async(&mut self) -> Result<u128>;
+    /// Read a 64-bit unsigned int
+    async fn read_u64_async(&mut self) -> Result<u64>;
+    /// Read a 32-bit unsigned int
+    async fn read_u32_async(&mut self) -> Result<u32>;
+    /// Read a 16-bit unsigned int
+    async fn read_u16_async(&mut self) -> Result<u16>;
+    /// Read an 8-bit unsigned int
+    async fn read_u8_async(&mut self) -> Result<u8>;
+
+    /// Read a 128-bit signed int
+    async fn read_i128_async(&mut self) -> Result<i128>;
+    /// Read a 64-bit signed int
+    async fn read_i64_async(&mut self) -> Result<i64>;
+    /// Ouptut a 32-bit signed int
+    async fn read_i32_async(&mut self) -> Result<i32>;
+    /// Read a 16-bit signed int
+    async fn read_i16_async(&mut self) -> Result<i16>;
+    /// Read an 8-bit signed int
+    async fn read_i8_async(&mut self) -> Result<i8>;
+
+    /// Read a 64-bit floating point int
+    async fn read_f64_async(&mut self) -> Result<f64>;
+    /// Read a 32-bit floating point int
+    async fn read_f32_async(&mut self) -> Result<f32>;
+
+    /// Read a boolean
+    async fn read_bool_async(&mut self) -> Result<bool>;
+
+    /// Read a byte slice
+    async fn read_slice_async(&mut self, slice: &mut [u8]) -> Result<()>;
+}
+
+#[async_trait]
+impl<W: AsyncWrite + Unpin + Send> AsyncWriteExt for W {
+    #[inline]
+    async fn write_u128_async(&mut self, v: u128) -> Result<()> {
+        self.write_all(&endian::u128_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_u64_async(&mut self, v: u64) -> Result<()> {
+        self.write_all(&endian::u64_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_u32_async(&mut self, v: u32) -> Result<()> {
+        self.write_all(&endian::u32_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_u16_async(&mut self, v: u16) -> Result<()> {
+        self.write_all(&endian::u16_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_u8_async(&mut self, v: u8) -> Result<()> {
+        self.write_all(&[v]).await
+    }
+
+    #[inline]
+    async fn write_i128_async(&mut self, v: i128) -> Result<()> {
+        self.write_all(&endian::i128_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_i64_async(&mut self, v: i64) -> Result<()> {
+        self.write_all(&endian::i64_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_i32_async(&mut self, v: i32) -> Result<()> {
+        self.write_all(&endian::i32_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_i16_async(&mut self, v: i16) -> Result<()> {
+        self.write_all(&endian::i16_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_i8_async(&mut self, v: i8) -> Result<()> {
+        self.write_all(&[v as u8]).await
+    }
+
+    #[inline]
+    async fn write_f64_async(&mut self, v: f64) -> Result<()> {
+        self.write_all(&endian::f64_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_f32_async(&mut self, v: f32) -> Result<()> {
+        self.write_all(&endian::f32_to_array_le(v)).await
+    }
+
+    #[inline]
+    async fn write_bool_async(&mut self, v: bool) -> Result<()> {
+        self.write_all(&[v as u8]).await
+    }
+
+    #[inline]
+    async fn write_slice_async(&mut self, v: &[u8]) -> Result<()> {
+        self.write_all(v).await
+    }
+}
+
+#[async_trait]
+impl<R: AsyncRead + Unpin + Send> AsyncReadExt for R {
+    #[inline]
+    async fn read_u128_async(&mut self) -> Result<u128> {
+        let mut val = [0; 16];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_u128_le(&val))
+    }
+
+    #[inline]
+    async fn read_u64_async(&mut self) -> Result<u64> {
+        let mut val = [0; 8];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_u64_le(&val))
+    }
+
+    #[inline]
+    async fn read_u32_async(&mut self) -> Result<u32> {
+        let mut val = [0; 4];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_u32_le(&val))
+    }
+
+    #[inline]
+    async fn read_u16_async(&mut self) -> Result<u16> {
+        let mut val = [0; 2];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_u16_le(&val))
+    }
+
+    #[inline]
+    async fn read_u8_async(&mut self) -> Result<u8> {
+        let mut val = [0; 1];
+        self.read_exact(&mut val[..]).await?;
+        Ok(val[0])
+    }
+
+    #[inline]
+    async fn read_i128_async(&mut self) -> Result<i128> {
+        let mut val = [0; 16];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_i128_le(&val))
+    }
+
+    #[inline]
+    async fn read_i64_async(&mut self) -> Result<i64> {
+        let mut val = [0; 8];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_i64_le(&val))
+    }
+
+    #[inline]
+    async fn read_i32_async(&mut self) -> Result<i32> {
+        let mut val = [0; 4];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_i32_le(&val))
+    }
+
+    #[inline]
+    async fn read_i16_async(&mut self) -> Result<i16> {
+        let mut val = [0; 2];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_i16_le(&val))
+    }
+
+    #[inline]
+    async fn read_i8_async(&mut self) -> Result<i8> {
+        let mut val = [0; 1];
+        self.read_exact(&mut val[..]).await?;
+        Ok(val[0] as i8)
+    }
+
+    #[inline]
+    async fn read_f64_async(&mut self) -> Result<f64> {
+        let mut val = [0; 8];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_f64_le(&val))
+    }
+
+    #[inline]
+    async fn read_f32_async(&mut self) -> Result<f32> {
+        let mut val = [0; 4];
+        self.read_exact(&mut val[..]).await?;
+        Ok(endian::slice_to_f32_le(&val))
+    }
+
+    #[inline]
+    async fn read_bool_async(&mut self) -> Result<bool> {
+        AsyncReadExt::read_i8_async(self).await.map(|bit| bit != 0)
+    }
+
+    #[inline]
+    async fn read_slice_async(&mut self, slice: &mut [u8]) -> Result<()> {
+        self.read_exact(slice).await
+    }
+}
+
+macro_rules! impl_int_encodable {
+    ($ty:ident, $meth_dec:ident, $meth_enc:ident) => {
+        #[async_trait]
+        impl AsyncDecodable for $ty {
+            #[inline]
+            async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+                AsyncReadExt::$meth_dec(d).await.map($ty::from_le)
+            }
+        }
+
+        #[async_trait]
+        impl AsyncEncodable for $ty {
+            #[inline]
+            async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+                s.$meth_enc(self.to_le()).await?;
+                Ok(core::mem::size_of::<$ty>())
+            }
+        }
+    };
+}
+
+impl_int_encodable!(u8, read_u8_async, write_u8_async);
+impl_int_encodable!(u16, read_u16_async, write_u16_async);
+impl_int_encodable!(u32, read_u32_async, write_u32_async);
+impl_int_encodable!(u64, read_u64_async, write_u64_async);
+impl_int_encodable!(u128, read_u128_async, write_u128_async);
+
+impl_int_encodable!(i8, read_i8_async, write_i8_async);
+impl_int_encodable!(i16, read_i16_async, write_i16_async);
+impl_int_encodable!(i32, read_i32_async, write_i32_async);
+impl_int_encodable!(i64, read_i64_async, write_i64_async);
+impl_int_encodable!(i128, read_i128_async, write_i128_async);
+
+macro_rules! tuple_encode {
+    ($($x:ident),*) => (
+        #[async_trait]
+        impl<$($x: AsyncEncodable + Sync),*> AsyncEncodable for ($($x),*) {
+            #[inline]
+            #[allow(non_snake_case)]
+            async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+                let &($(ref $x),*) = self;
+                let mut len = 0;
+                $(len += $x.encode_async(s).await?;)*
+                Ok(len)
+            }
+        }
+
+        #[async_trait]
+        impl<$($x: AsyncDecodable + Send),*> AsyncDecodable for ($($x),*) {
+            #[inline]
+            #[allow(non_snake_case)]
+            async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+                Ok(($({let $x = AsyncDecodable::decode_async(d).await?; $x }),*))
+            }
+        }
+    )
+}
+
+tuple_encode!(T0, T1);
+tuple_encode!(T0, T1, T2);
+tuple_encode!(T0, T1, T2, T3);
+tuple_encode!(T0, T1, T2, T3, T4);
+tuple_encode!(T0, T1, T2, T3, T4, T5);
+tuple_encode!(T0, T1, T2, T3, T4, T5, T6);
+tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7);
+
+/// Asynchronously encode a dynamic set of arguments to a buffer.
+#[macro_export]
+macro_rules! encode_payload_async {
+    ($buf:expr, $($args:expr),*) => {{ $( $args.encode_async($buf).await?;)* }}
+}
+
+#[async_trait]
+impl AsyncEncodable for VarInt {
+    #[inline]
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        match self.0 {
+            0..=0xFC => {
+                (self.0 as u8).encode_async(s).await?;
+                Ok(1)
+            }
+
+            0xFD..=0xFFFF => {
+                s.write_u8_async(0xFD).await?;
+                (self.0 as u16).encode_async(s).await?;
+                Ok(3)
+            }
+
+            0x10000..=0xFFFFFFFF => {
+                s.write_u8_async(0xFE).await?;
+                (self.0 as u32).encode_async(s).await?;
+                Ok(5)
+            }
+
+            _ => {
+                s.write_u8_async(0xFF).await?;
+                self.0.encode_async(s).await?;
+                Ok(9)
+            }
+        }
+    }
+}
+
+#[async_trait]
+impl AsyncDecodable for VarInt {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let n = AsyncReadExt::read_u8_async(d).await?;
+        match n {
+            0xFF => {
+                let x = AsyncReadExt::read_u64_async(d).await?;
+                if x < 0x100000000 {
+                    return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt"))
+                }
+                Ok(VarInt(x))
+            }
+
+            0xFE => {
+                let x = AsyncReadExt::read_u32_async(d).await?;
+                if x < 0x10000 {
+                    return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt"))
+                }
+                Ok(VarInt(x as u64))
+            }
+
+            0xFD => {
+                let x = AsyncReadExt::read_u16_async(d).await?;
+                if x < 0xFD {
+                    return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt"))
+                }
+                Ok(VarInt(x as u64))
+            }
+
+            n => Ok(VarInt(n as u64)),
+        }
+    }
+}
+
+// Implementations for some primitive types
+#[async_trait]
+impl AsyncEncodable for usize {
+    #[inline]
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_u64_async(*self as u64).await?;
+        Ok(8)
+    }
+}
+
+#[async_trait]
+impl AsyncDecodable for usize {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        Ok(AsyncReadExt::read_u64_async(d).await? as usize)
+    }
+}
+
+#[async_trait]
+impl AsyncEncodable for f64 {
+    #[inline]
+    async fn encode_async<S: AsyncWriteExt + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_f64_async(*self).await?;
+        Ok(core::mem::size_of::<f64>())
+    }
+}
+
+#[async_trait]
+impl AsyncDecodable for f64 {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        AsyncReadExt::read_f64_async(d).await
+    }
+}
+
+#[async_trait]
+impl AsyncEncodable for f32 {
+    #[inline]
+    async fn encode_async<S: AsyncWriteExt + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_f32_async(*self).await?;
+        Ok(core::mem::size_of::<f32>())
+    }
+}
+
+#[async_trait]
+impl AsyncDecodable for f32 {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        AsyncReadExt::read_f32_async(d).await
+    }
+}
+
+#[async_trait]
+impl AsyncEncodable for bool {
+    #[inline]
+    async fn encode_async<S: AsyncWriteExt + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_bool_async(*self).await?;
+        Ok(1)
+    }
+}
+
+#[async_trait]
+impl AsyncDecodable for bool {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        AsyncReadExt::read_bool_async(d).await
+    }
+}
+
+#[async_trait]
+impl<T: AsyncEncodable + Sync> AsyncEncodable for Vec<T> {
+    #[inline]
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode_async(s).await?;
+        for val in self {
+            len += val.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
+#[async_trait]
+impl<T: AsyncDecodable + Send> AsyncDecodable for Vec<T> {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let len = VarInt::decode_async(d).await?.0;
+        let mut ret = Vec::with_capacity(len as usize);
+        for _ in 0..len {
+            ret.push(AsyncDecodable::decode_async(d).await?);
+        }
+        Ok(ret)
+    }
+}
+
+#[async_trait]
+impl<T: AsyncEncodable + Sync> AsyncEncodable for VecDeque<T> {
+    #[inline]
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode_async(s).await?;
+        for val in self {
+            len += val.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
+#[async_trait]
+impl<T: AsyncDecodable + Send> AsyncDecodable for VecDeque<T> {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let len = VarInt::decode_async(d).await?.0;
+        let mut ret = VecDeque::with_capacity(len as usize);
+        for _ in 0..len {
+            ret.push_back(AsyncDecodable::decode_async(d).await?);
+        }
+        Ok(ret)
+    }
+}
+
+#[async_trait]
+impl<T: AsyncEncodable + Sync> AsyncEncodable for Option<T> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        if let Some(v) = self {
+            len += true.encode_async(s).await?;
+            len += v.encode_async(s).await?;
+        } else {
+            len += false.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
+#[async_trait]
+impl<T: AsyncDecodable> AsyncDecodable for Option<T> {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let valid: bool = AsyncDecodable::decode_async(d).await?;
+        let val = if valid { Some(AsyncDecodable::decode_async(d).await?) } else { None };
+        Ok(val)
+    }
+}
+
+#[async_trait]
+impl<const N: usize> AsyncEncodable for [u8; N] {
+    #[inline]
+    async fn encode_async<S: AsyncWriteExt + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_slice_async(&self[..]).await?;
+        Ok(self.len())
+    }
+}
+
+#[async_trait]
+impl<const N: usize> AsyncDecodable for [u8; N] {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let mut ret = [0; N];
+        d.read_slice_async(&mut ret).await?;
+        Ok(ret)
+    }
+}
+
+#[async_trait]
+impl AsyncEncodable for String {
+    #[inline]
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let b = self.as_bytes();
+        let b_len = b.len();
+        let vi_len = VarInt(b_len as u64).encode_async(s).await?;
+        s.write_slice_async(b).await?;
+        Ok(vi_len + b_len)
+    }
+}
+
+#[async_trait]
+impl AsyncEncodable for &str {
+    #[inline]
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let b = self.as_bytes();
+        let b_len = b.len();
+        let vi_len = VarInt(b_len as u64).encode_async(s).await?;
+        s.write_slice_async(b).await?;
+        Ok(vi_len + b_len)
+    }
+}
+
+#[async_trait]
+impl AsyncDecodable for String {
+    #[inline]
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<String> {
+        match String::from_utf8(AsyncDecodable::decode_async(d).await?) {
+            Ok(v) => Ok(v),
+            Err(_) => Err(Error::new(ErrorKind::Other, "Invalid UTF-8 for string")),
+        }
+    }
+}

+ 0 - 143
src/serial/src/async_serial.rs

@@ -1,143 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::io::{Error, ErrorKind};
-
-use futures_lite::{
-    AsyncRead, AsyncReadExt as AsyncReadExtFut, AsyncWrite, AsyncWriteExt as AsyncWriteExtFut,
-};
-
-use super::{endian, VarInt};
-
-pub struct AsyncReadExt;
-pub struct AsyncWriteExt;
-
-macro_rules! async_decoder_fn {
-    ($name:ident, $val_type:ty, $readfn:ident, $byte_len:expr) => {
-        #[inline]
-        pub async fn $name<R: AsyncRead + Unpin>(stream: &mut R) -> Result<$val_type, Error> {
-            assert_eq!(core::mem::size_of::<$val_type>(), $byte_len);
-            let mut val = [0; $byte_len];
-            stream.read_exact(&mut val[..]).await?;
-            Ok(endian::$readfn(&val))
-        }
-    };
-}
-
-macro_rules! async_encoder_fn {
-    ($name:ident, $val_type:ty, $writefn:ident) => {
-        #[inline]
-        pub async fn $name<W: AsyncWrite + Unpin>(
-            stream: &mut W,
-            v: $val_type,
-        ) -> Result<(), Error> {
-            stream.write_all(&endian::$writefn(v)).await
-        }
-    };
-}
-
-#[allow(dead_code)]
-impl AsyncReadExt {
-    async_decoder_fn!(read_u128, u128, slice_to_u128_le, 16);
-    async_decoder_fn!(read_u64, u64, slice_to_u64_le, 8);
-    async_decoder_fn!(read_u32, u32, slice_to_u32_le, 4);
-    async_decoder_fn!(read_u16, u16, slice_to_u16_le, 2);
-
-    pub async fn read_u8<R: AsyncRead + Unpin>(stream: &mut R) -> Result<u8, Error> {
-        let mut slice = [0u8; 1];
-        stream.read_exact(&mut slice).await?;
-        Ok(slice[0])
-    }
-}
-
-#[allow(dead_code)]
-impl AsyncWriteExt {
-    async_encoder_fn!(write_u128, u128, u128_to_array_le);
-    async_encoder_fn!(write_u64, u64, u64_to_array_le);
-    async_encoder_fn!(write_u32, u32, u32_to_array_le);
-    async_encoder_fn!(write_u16, u16, u16_to_array_le);
-
-    pub async fn write_u8<W: AsyncWrite + Unpin>(stream: &mut W, v: u8) -> Result<(), Error> {
-        stream.write_all(&[v]).await
-    }
-}
-
-impl VarInt {
-    #[inline]
-    pub async fn encode_async<W: AsyncWrite + Unpin>(
-        &self,
-        stream: &mut W,
-    ) -> Result<usize, Error> {
-        match self.0 {
-            0..=0xFC => {
-                AsyncWriteExt::write_u8(stream, self.0 as u8).await?;
-                Ok(1)
-            }
-
-            0xFD..=0xFFFF => {
-                AsyncWriteExt::write_u8(stream, 0xFD).await?;
-                AsyncWriteExt::write_u16(stream, self.0 as u16).await?;
-                Ok(3)
-            }
-
-            0x10000..=0xFFFFFFFF => {
-                AsyncWriteExt::write_u8(stream, 0xFE).await?;
-                AsyncWriteExt::write_u32(stream, self.0 as u32).await?;
-                Ok(5)
-            }
-
-            _ => {
-                AsyncWriteExt::write_u8(stream, 0xFF).await?;
-                AsyncWriteExt::write_u64(stream, self.0).await?;
-                Ok(9)
-            }
-        }
-    }
-
-    #[inline]
-    pub async fn decode_async<R: AsyncRead + Unpin>(stream: &mut R) -> Result<Self, Error> {
-        let n = AsyncReadExt::read_u8(stream).await?;
-        match n {
-            0xFF => {
-                let x = AsyncReadExt::read_u64(stream).await?;
-                if x < 0x100000000 {
-                    return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt"))
-                }
-                Ok(VarInt(x))
-            }
-
-            0xFE => {
-                let x = AsyncReadExt::read_u32(stream).await?;
-                if x < 0x10000 {
-                    return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt"))
-                }
-                Ok(VarInt(x as u64))
-            }
-
-            0xFD => {
-                let x = AsyncReadExt::read_u16(stream).await?;
-                if x < 0xFD {
-                    return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt"))
-                }
-                Ok(VarInt(x as u64))
-            }
-
-            n => Ok(VarInt(n as u64)),
-        }
-    }
-}

+ 5 - 1
src/serial/src/lib.rs

@@ -25,7 +25,11 @@ use std::{
 pub use darkfi_derive::{SerialDecodable, SerialEncodable};
 
 #[cfg(feature = "async")]
-mod async_serial;
+mod async_lib;
+#[cfg(feature = "async")]
+pub use async_lib::{
+    deserialize_async, deserialize_async_partial, serialize_async, AsyncDecodable, AsyncEncodable,
+};
 
 mod endian;
 mod types;

+ 0 - 3
src/serial/src/types.rs

@@ -33,8 +33,5 @@ mod pasta;
 #[cfg(feature = "url")]
 mod url;
 
-#[cfg(feature = "x25519-dalek")]
-mod x25519;
-
 #[cfg(feature = "semver")]
 mod semver;

+ 177 - 13
src/serial/src/types/bridgetree.rs

@@ -17,25 +17,49 @@
  */
 
 use core::fmt::Debug;
-use std::io::{Error, ErrorKind, Read, Write};
+use std::io::{Error, ErrorKind, Read, Result, Write};
+
+#[cfg(feature = "async")]
+use crate::{AsyncDecodable, AsyncEncodable};
+#[cfg(feature = "async")]
+use async_trait::async_trait;
+#[cfg(feature = "async")]
+use futures_lite::{AsyncRead, AsyncWrite};
 
 use crate::{Decodable, Encodable};
 
 impl Encodable for bridgetree::Position {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         u64::from(*self).encode(&mut s)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for bridgetree::Position {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        u64::from(*self).encode_async(s).await
+    }
+}
+
 impl Decodable for bridgetree::Position {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let dec: u64 = Decodable::decode(&mut d)?;
         Ok(Self::try_from(dec).unwrap())
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for bridgetree::Position {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let dec: u64 = AsyncDecodable::decode_async(d).await?;
+        Ok(Self::try_from(dec).unwrap())
+    }
+}
+
 impl Encodable for bridgetree::Address {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += u8::from(self.level()).encode(&mut s)?;
         len += self.index().encode(&mut s)?;
@@ -43,16 +67,37 @@ impl Encodable for bridgetree::Address {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for bridgetree::Address {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += u8::from(self.level()).encode_async(s).await?;
+        len += self.index().encode_async(s).await?;
+        Ok(len)
+    }
+}
+
 impl Decodable for bridgetree::Address {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let level: u8 = Decodable::decode(&mut d)?;
         let index = Decodable::decode(&mut d)?;
         Ok(Self::from_parts(level.into(), index))
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for bridgetree::Address {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let level: u8 = AsyncDecodable::decode_async(d).await?;
+        let index = AsyncDecodable::decode_async(d).await?;
+        Ok(Self::from_parts(level.into(), index))
+    }
+}
+
 impl<H: Encodable + Ord + Clone> Encodable for bridgetree::NonEmptyFrontier<H> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.position().encode(&mut s)?;
         len += self.leaf().encode(&mut s)?;
@@ -61,8 +106,22 @@ impl<H: Encodable + Ord + Clone> Encodable for bridgetree::NonEmptyFrontier<H> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<H: AsyncEncodable + Sync + Send + Ord + Clone> AsyncEncodable
+    for bridgetree::NonEmptyFrontier<H>
+{
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += self.position().encode_async(s).await?;
+        len += self.leaf().encode_async(s).await?;
+        len += self.ommers().to_vec().encode_async(s).await?;
+        Ok(len)
+    }
+}
+
 impl<H: Decodable + Ord + Clone> Decodable for bridgetree::NonEmptyFrontier<H> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let position = Decodable::decode(&mut d)?;
         let leaf = Decodable::decode(&mut d)?;
         let ommers = Decodable::decode(&mut d)?;
@@ -74,8 +133,23 @@ impl<H: Decodable + Ord + Clone> Decodable for bridgetree::NonEmptyFrontier<H> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<H: AsyncDecodable + Send + Ord + Clone> AsyncDecodable for bridgetree::NonEmptyFrontier<H> {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let position = AsyncDecodable::decode_async(d).await?;
+        let leaf = AsyncDecodable::decode_async(d).await?;
+        let ommers = AsyncDecodable::decode_async(d).await?;
+
+        match Self::from_parts(position, leaf, ommers) {
+            Ok(v) => Ok(v),
+            Err(_) => Err(Error::new(ErrorKind::Other, "FrontierError")),
+        }
+    }
+}
+
 impl<H: Encodable + Ord + Clone> Encodable for bridgetree::MerkleBridge<H> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.prior_position().encode(&mut s)?;
         len += self.tracking().encode(&mut s)?;
@@ -85,8 +159,21 @@ impl<H: Encodable + Ord + Clone> Encodable for bridgetree::MerkleBridge<H> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<H: AsyncEncodable + Sync + Send + Ord + Clone> AsyncEncodable for bridgetree::MerkleBridge<H> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += self.prior_position().encode_async(s).await?;
+        len += self.tracking().encode_async(s).await?;
+        len += self.ommers().encode_async(s).await?;
+        len += self.frontier().encode_async(s).await?;
+        Ok(len)
+    }
+}
+
 impl<H: Decodable + Ord + Clone> Decodable for bridgetree::MerkleBridge<H> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let prior_position = Decodable::decode(&mut d)?;
         let tracking = Decodable::decode(&mut d)?;
         let ommers = Decodable::decode(&mut d)?;
@@ -95,8 +182,20 @@ impl<H: Decodable + Ord + Clone> Decodable for bridgetree::MerkleBridge<H> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<H: AsyncDecodable + Send + Ord + Clone> AsyncDecodable for bridgetree::MerkleBridge<H> {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let prior_position = AsyncDecodable::decode_async(d).await?;
+        let tracking = AsyncDecodable::decode_async(d).await?;
+        let ommers = AsyncDecodable::decode_async(d).await?;
+        let frontier = AsyncDecodable::decode_async(d).await?;
+        Ok(Self::from_parts(prior_position, tracking, ommers, frontier))
+    }
+}
+
 impl<C: Encodable> Encodable for bridgetree::Checkpoint<C> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.id().encode(&mut s)?;
         len += self.bridges_len().encode(&mut s)?;
@@ -106,8 +205,21 @@ impl<C: Encodable> Encodable for bridgetree::Checkpoint<C> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<C: AsyncEncodable + Sync> AsyncEncodable for bridgetree::Checkpoint<C> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += self.id().encode_async(s).await?;
+        len += self.bridges_len().encode_async(s).await?;
+        len += self.marked().encode_async(s).await?;
+        len += self.forgotten().encode_async(s).await?;
+        Ok(len)
+    }
+}
+
 impl<C: Decodable> Decodable for bridgetree::Checkpoint<C> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let id = Decodable::decode(&mut d)?;
         let bridges_len = Decodable::decode(&mut d)?;
         let marked = Decodable::decode(&mut d)?;
@@ -116,10 +228,22 @@ impl<C: Decodable> Decodable for bridgetree::Checkpoint<C> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<C: AsyncDecodable + Send> AsyncDecodable for bridgetree::Checkpoint<C> {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let id = AsyncDecodable::decode_async(d).await?;
+        let bridges_len = AsyncDecodable::decode_async(d).await?;
+        let marked = AsyncDecodable::decode_async(d).await?;
+        let forgotten = AsyncDecodable::decode_async(d).await?;
+        Ok(Self::from_parts(id, bridges_len, marked, forgotten))
+    }
+}
+
 impl<H: Encodable + Ord + Clone, C: Encodable + Debug, const DEPTH: u8> Encodable
     for bridgetree::BridgeTree<H, C, DEPTH>
 {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.prior_bridges().to_vec().encode(&mut s)?;
         len += self.current_bridge().encode(&mut s)?;
@@ -130,13 +254,32 @@ impl<H: Encodable + Ord + Clone, C: Encodable + Debug, const DEPTH: u8> Encodabl
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<
+        H: AsyncEncodable + Sync + Send + Ord + Clone,
+        C: AsyncEncodable + Sync + Debug,
+        const DEPTH: u8,
+    > AsyncEncodable for bridgetree::BridgeTree<H, C, DEPTH>
+{
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += self.prior_bridges().to_vec().encode_async(s).await?;
+        len += self.current_bridge().encode_async(s).await?;
+        len += self.marked_indices().encode_async(s).await?;
+        len += self.checkpoints().encode_async(s).await?;
+        len += self.max_checkpoints().encode_async(s).await?;
+        Ok(len)
+    }
+}
+
 impl<
         H: Decodable + Clone + Ord + bridgetree::Hashable,
         C: Decodable + Clone + Ord + Eq + Debug,
         const DEPTH: u8,
     > Decodable for bridgetree::BridgeTree<H, C, DEPTH>
 {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let prior_bridges = Decodable::decode(&mut d)?;
         let current_bridge = Decodable::decode(&mut d)?;
         let saved = Decodable::decode(&mut d)?;
@@ -149,6 +292,27 @@ impl<
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<
+        H: AsyncDecodable + Send + Clone + Ord + bridgetree::Hashable,
+        C: AsyncDecodable + Send + Clone + Ord + Eq + Debug,
+        const DEPTH: u8,
+    > AsyncDecodable for bridgetree::BridgeTree<H, C, DEPTH>
+{
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let prior_bridges = AsyncDecodable::decode_async(d).await?;
+        let current_bridge = AsyncDecodable::decode_async(d).await?;
+        let saved = AsyncDecodable::decode_async(d).await?;
+        let checkpoints = AsyncDecodable::decode_async(d).await?;
+        let max_checkpoints = AsyncDecodable::decode_async(d).await?;
+        match Self::from_parts(prior_bridges, current_bridge, saved, checkpoints, max_checkpoints) {
+            Ok(v) => Ok(v),
+            Err(_) => Err(Error::new(ErrorKind::Other, "BridgeTreeError")),
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::{deserialize, serialize, SerialDecodable, SerialEncodable};

+ 138 - 15
src/serial/src/types/collections.rs

@@ -19,13 +19,20 @@
 //! Serialization of collections
 use std::{
     collections::{BTreeMap, BTreeSet, HashMap, HashSet},
-    io::{Error, Read, Write},
+    io::{Read, Result, Write},
 };
 
+#[cfg(feature = "async")]
+use crate::{AsyncDecodable, AsyncEncodable};
+#[cfg(feature = "async")]
+use async_trait::async_trait;
+#[cfg(feature = "async")]
+use futures_lite::{AsyncRead, AsyncWrite};
+
 use crate::{Decodable, Encodable, VarInt};
 
 impl<T: Encodable> Encodable for HashSet<T> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += VarInt(self.len() as u64).encode(&mut s)?;
         for c in self.iter() {
@@ -35,8 +42,21 @@ impl<T: Encodable> Encodable for HashSet<T> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncEncodable + Sync> AsyncEncodable for HashSet<T> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode_async(s).await?;
+        for c in self.iter() {
+            len += c.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
 impl<T: Decodable + std::cmp::Eq + std::hash::Hash> Decodable for HashSet<T> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let len = VarInt::decode(&mut d)?.0;
         let mut ret = HashSet::new();
         for _ in 0..len {
@@ -47,8 +67,22 @@ impl<T: Decodable + std::cmp::Eq + std::hash::Hash> Decodable for HashSet<T> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncDecodable + Send + std::cmp::Eq + std::hash::Hash> AsyncDecodable for HashSet<T> {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let len = VarInt::decode_async(d).await?.0;
+        let mut ret = HashSet::new();
+        for _ in 0..len {
+            let entry: T = AsyncDecodable::decode_async(d).await?;
+            ret.insert(entry);
+        }
+        Ok(ret)
+    }
+}
+
 impl<T: Encodable, U: Encodable> Encodable for BTreeMap<T, U> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += VarInt(self.len() as u64).encode(&mut s)?;
         for c in self.iter() {
@@ -59,8 +93,22 @@ impl<T: Encodable, U: Encodable> Encodable for BTreeMap<T, U> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncEncodable + Sync, U: AsyncEncodable + Sync> AsyncEncodable for BTreeMap<T, U> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode_async(s).await?;
+        for c in self.iter() {
+            len += c.0.encode_async(s).await?;
+            len += c.1.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
 impl<T: Decodable + std::cmp::Ord, U: Decodable> Decodable for BTreeMap<T, U> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let len = VarInt::decode(&mut d)?.0;
         let mut ret = BTreeMap::new();
         for _ in 0..len {
@@ -72,8 +120,25 @@ impl<T: Decodable + std::cmp::Ord, U: Decodable> Decodable for BTreeMap<T, U> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncDecodable + Send + std::cmp::Ord, U: AsyncDecodable + Send> AsyncDecodable
+    for BTreeMap<T, U>
+{
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let len = VarInt::decode_async(d).await?.0;
+        let mut ret = BTreeMap::new();
+        for _ in 0..len {
+            let key: T = AsyncDecodable::decode_async(d).await?;
+            let entry: U = AsyncDecodable::decode_async(d).await?;
+            ret.insert(key, entry);
+        }
+        Ok(ret)
+    }
+}
+
 impl<T: Encodable> Encodable for BTreeSet<T> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += VarInt(self.len() as u64).encode(&mut s)?;
         for c in self.iter() {
@@ -83,8 +148,21 @@ impl<T: Encodable> Encodable for BTreeSet<T> {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncEncodable + Sync> AsyncEncodable for BTreeSet<T> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode_async(s).await?;
+        for c in self.iter() {
+            len += c.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
 impl<T: Decodable + std::cmp::Ord> Decodable for BTreeSet<T> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let len = VarInt::decode(&mut d)?.0;
         let mut ret = BTreeSet::new();
         for _ in 0..len {
@@ -95,21 +173,22 @@ impl<T: Decodable + std::cmp::Ord> Decodable for BTreeSet<T> {
     }
 }
 
-impl<T: Decodable + std::cmp::Eq + std::hash::Hash, U: Decodable> Decodable for HashMap<T, U> {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
-        let len = VarInt::decode(&mut d)?.0;
-        let mut ret = HashMap::new();
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncDecodable + Send + std::cmp::Ord> AsyncDecodable for BTreeSet<T> {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let len = VarInt::decode_async(d).await?.0;
+        let mut ret = BTreeSet::new();
         for _ in 0..len {
-            let key: T = Decodable::decode(&mut d)?;
-            let entry: U = Decodable::decode(&mut d)?;
-            ret.insert(key, entry);
+            let key: T = AsyncDecodable::decode_async(d).await?;
+            ret.insert(key);
         }
         Ok(ret)
     }
 }
 
 impl<T: Encodable, U: Encodable> Encodable for HashMap<T, U> {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += VarInt(self.len() as u64).encode(&mut s)?;
         for c in self.iter() {
@@ -119,3 +198,47 @@ impl<T: Encodable, U: Encodable> Encodable for HashMap<T, U> {
         Ok(len)
     }
 }
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncEncodable + Sync, U: AsyncEncodable + Sync> AsyncEncodable for HashMap<T, U> {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode_async(s).await?;
+        for c in self.iter() {
+            len += c.0.encode_async(s).await?;
+            len += c.1.encode_async(s).await?;
+        }
+        Ok(len)
+    }
+}
+
+impl<T: Decodable + std::cmp::Eq + std::hash::Hash, U: Decodable> Decodable for HashMap<T, U> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
+        let len = VarInt::decode(&mut d)?.0;
+        let mut ret = HashMap::new();
+        for _ in 0..len {
+            let key: T = Decodable::decode(&mut d)?;
+            let entry: U = Decodable::decode(&mut d)?;
+            ret.insert(key, entry);
+        }
+        Ok(ret)
+    }
+}
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl<T: AsyncDecodable + Send + std::cmp::Eq + std::hash::Hash, U: AsyncDecodable + Send>
+    AsyncDecodable for HashMap<T, U>
+{
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let len = VarInt::decode_async(d).await?.0;
+        let mut ret = HashMap::new();
+        for _ in 0..len {
+            let key: T = AsyncDecodable::decode_async(d).await?;
+            let entry: U = AsyncDecodable::decode_async(d).await?;
+            ret.insert(key, entry);
+        }
+        Ok(ret)
+    }
+}

+ 32 - 3
src/serial/src/types/hash.rs

@@ -16,23 +16,52 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::io::{Error, Read, Write};
+use std::io::{Read, Result, Write};
+
+#[cfg(feature = "async")]
+use crate::{
+    async_lib::{AsyncReadExt, AsyncWriteExt},
+    AsyncDecodable, AsyncEncodable,
+};
+#[cfg(feature = "async")]
+use async_trait::async_trait;
+#[cfg(feature = "async")]
+use futures_lite::{AsyncRead, AsyncWrite};
 
 use crate::{Decodable, Encodable, ReadExt, WriteExt};
 
 #[cfg(feature = "blake3")]
 impl Encodable for blake3::Hash {
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         s.write_slice(self.as_bytes())?;
         Ok(32)
     }
 }
 
+#[cfg(all(feature = "blake3", feature = "async"))]
+#[async_trait]
+impl AsyncEncodable for blake3::Hash {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_slice_async(self.as_bytes()).await?;
+        Ok(blake3::OUT_LEN)
+    }
+}
+
 #[cfg(feature = "blake3")]
 impl Decodable for blake3::Hash {
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let mut bytes = [0u8; 32];
         d.read_slice(&mut bytes)?;
         Ok(bytes.into())
     }
 }
+
+#[cfg(all(feature = "blake3", feature = "async"))]
+#[async_trait]
+impl AsyncDecodable for blake3::Hash {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let mut bytes = [0u8; blake3::OUT_LEN];
+        d.read_slice_async(&mut bytes).await?;
+        Ok(bytes.into())
+    }
+}

+ 106 - 17
src/serial/src/types/pasta.rs

@@ -17,7 +17,17 @@
  */
 
 //! Implementations for pasta curves
-use std::io::{Error, ErrorKind, Read, Write};
+use std::io::{Error, ErrorKind, Read, Result, Write};
+
+#[cfg(feature = "async")]
+use crate::{
+    async_lib::{AsyncReadExt, AsyncWriteExt},
+    AsyncDecodable, AsyncEncodable,
+};
+#[cfg(feature = "async")]
+use async_trait::async_trait;
+#[cfg(feature = "async")]
+use futures_lite::{AsyncRead, AsyncWrite};
 
 use pasta_curves::{
     group::{ff::PrimeField, GroupEncoding},
@@ -27,16 +37,23 @@ use pasta_curves::{
 use crate::{Decodable, Encodable, ReadExt, WriteExt};
 
 impl Encodable for Fp {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         s.write_slice(&self.to_repr())?;
         Ok(32)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for Fp {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_slice_async(&self.to_repr()).await?;
+        Ok(32)
+    }
+}
+
 impl Decodable for Fp {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let mut bytes = [0u8; 32];
         d.read_slice(&mut bytes)?;
         match Self::from_repr(bytes).into() {
@@ -45,18 +62,37 @@ impl Decodable for Fp {
         }
     }
 }
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for Fp {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice_async(&mut bytes).await?;
+        match Self::from_repr(bytes).into() {
+            Some(v) => Ok(v),
+            None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for pallas::Base")),
+        }
+    }
+}
 
 impl Encodable for Fq {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         s.write_slice(&self.to_repr())?;
         Ok(32)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for Fq {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_slice_async(&self.to_repr()).await?;
+        Ok(32)
+    }
+}
+
 impl Decodable for Fq {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let mut bytes = [0u8; 32];
         d.read_slice(&mut bytes)?;
         match Self::from_repr(bytes).into() {
@@ -66,17 +102,37 @@ impl Decodable for Fq {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for Fq {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice_async(&mut bytes).await?;
+        match Self::from_repr(bytes).into() {
+            Some(v) => Ok(v),
+            None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for pallas::Scalar")),
+        }
+    }
+}
+
 impl Encodable for Ep {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         s.write_slice(&self.to_bytes())?;
         Ok(32)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for Ep {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_slice_async(&self.to_bytes()).await?;
+        Ok(32)
+    }
+}
+
 impl Decodable for Ep {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let mut bytes = [0u8; 32];
         d.read_slice(&mut bytes)?;
         match Self::from_bytes(&bytes).into() {
@@ -86,17 +142,37 @@ impl Decodable for Ep {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for Ep {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice_async(&mut bytes).await?;
+        match Self::from_bytes(&bytes).into() {
+            Some(v) => Ok(v),
+            None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for pallas::Point")),
+        }
+    }
+}
+
 impl Encodable for Eq {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         s.write_slice(&self.to_bytes())?;
         Ok(32)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for Eq {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        s.write_slice_async(&self.to_bytes()).await?;
+        Ok(32)
+    }
+}
+
 impl Decodable for Eq {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let mut bytes = [0u8; 32];
         d.read_slice(&mut bytes)?;
         match Self::from_bytes(&bytes).into() {
@@ -105,3 +181,16 @@ impl Decodable for Eq {
         }
     }
 }
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for Eq {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let mut bytes = [0u8; 32];
+        d.read_slice_async(&mut bytes).await?;
+        match Self::from_bytes(&bytes).into() {
+            Some(v) => Ok(v),
+            None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for vesta::Point")),
+        }
+    }
+}

+ 88 - 15
src/serial/src/types/semver.rs

@@ -16,51 +16,99 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::io::{Error, ErrorKind, Read, Write};
+use std::io::{Error, ErrorKind, Read, Result, Write};
+
+#[cfg(feature = "async")]
+use crate::{AsyncDecodable, AsyncEncodable};
+#[cfg(feature = "async")]
+use async_trait::async_trait;
+#[cfg(feature = "async")]
+use futures_lite::{AsyncRead, AsyncWrite};
 
 use crate::{Decodable, Encodable};
 
 impl Encodable for semver::Prerelease {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         self.as_str().encode(&mut s)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for semver::Prerelease {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        self.as_str().encode_async(s).await
+    }
+}
+
 impl Decodable for semver::Prerelease {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let s: String = Decodable::decode(&mut d)?;
 
         match Self::new(&s) {
             Ok(v) => Ok(v),
-            Err(_e) => Err(Error::new(ErrorKind::Other, "Failed parsing semver Prerelase")),
+            Err(_) => Err(Error::new(ErrorKind::Other, "Failed deserializing semver::Prerelase")),
+        }
+    }
+}
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for semver::Prerelease {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let s: String = AsyncDecodable::decode_async(d).await?;
+
+        match Self::new(&s) {
+            Ok(v) => Ok(v),
+            Err(_) => Err(Error::new(ErrorKind::Other, "Failed deserializing semver::Prerelease")),
         }
     }
 }
 
 impl Encodable for semver::BuildMetadata {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         self.as_str().encode(&mut s)
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for semver::BuildMetadata {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        self.as_str().encode_async(s).await
+    }
+}
+
 impl Decodable for semver::BuildMetadata {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let s: String = Decodable::decode(&mut d)?;
 
         match Self::new(&s) {
             Ok(v) => Ok(v),
-            Err(_e) => Err(Error::new(ErrorKind::Other, "Failed parsing semver BuildMetadata")),
+            Err(_) => {
+                Err(Error::new(ErrorKind::Other, "Failed deserializing semver::BuildMetadata"))
+            }
+        }
+    }
+}
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for semver::BuildMetadata {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let s: String = AsyncDecodable::decode_async(d).await?;
+
+        match Self::new(&s) {
+            Ok(v) => Ok(v),
+            Err(_) => {
+                Err(Error::new(ErrorKind::Other, "Failed deserializing semver::BuildMetadata"))
+            }
         }
     }
 }
 
 impl Encodable for semver::Version {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
+    fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.major.encode(&mut s)?;
         len += self.minor.encode(&mut s)?;
@@ -71,9 +119,22 @@ impl Encodable for semver::Version {
     }
 }
 
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for semver::Version {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        let mut len = 0;
+        len += self.major.encode_async(s).await?;
+        len += self.minor.encode_async(s).await?;
+        len += self.patch.encode_async(s).await?;
+        len += self.pre.encode_async(s).await?;
+        len += self.build.encode_async(s).await?;
+        Ok(len)
+    }
+}
+
 impl Decodable for semver::Version {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let major: u64 = Decodable::decode(&mut d)?;
         let minor: u64 = Decodable::decode(&mut d)?;
         let patch: u64 = Decodable::decode(&mut d)?;
@@ -82,6 +143,18 @@ impl Decodable for semver::Version {
         Ok(Self { major, minor, patch, pre, build })
     }
 }
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for semver::Version {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let major: u64 = AsyncDecodable::decode_async(d).await?;
+        let minor: u64 = AsyncDecodable::decode_async(d).await?;
+        let patch: u64 = AsyncDecodable::decode_async(d).await?;
+        let pre: semver::Prerelease = AsyncDecodable::decode_async(d).await?;
+        let build: semver::BuildMetadata = AsyncDecodable::decode_async(d).await?;
+        Ok(Self { major, minor, patch, pre, build })
+    }
+}
 
 #[cfg(test)]
 mod tests {

+ 31 - 7
src/serial/src/types/url.rs

@@ -16,22 +16,34 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::io::{Error, ErrorKind, Read, Write};
-
+use std::io::{Error, ErrorKind, Read, Result, Write};
 use url::Url;
 
+#[cfg(feature = "async")]
+use crate::{AsyncDecodable, AsyncEncodable};
+#[cfg(feature = "async")]
+use async_trait::async_trait;
+#[cfg(feature = "async")]
+use futures_lite::{AsyncRead, AsyncWrite};
+
 use crate::{Decodable, Encodable};
 
 impl Encodable for Url {
-    #[inline]
-    fn encode<S: Write>(&self, s: S) -> Result<usize, Error> {
-        self.as_str().to_string().encode(s)
+    fn encode<S: Write>(&self, s: S) -> Result<usize> {
+        self.as_str().encode(s)
+    }
+}
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncEncodable for Url {
+    async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        self.as_str().encode_async(s).await
     }
 }
 
 impl Decodable for Url {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
+    fn decode<D: Read>(mut d: D) -> Result<Self> {
         let s: String = Decodable::decode(&mut d)?;
         match Url::parse(&s) {
             Ok(v) => Ok(v),
@@ -39,3 +51,15 @@ impl Decodable for Url {
         }
     }
 }
+
+#[cfg(feature = "async")]
+#[async_trait]
+impl AsyncDecodable for Url {
+    async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
+        let s: String = AsyncDecodable::decode_async(d).await?;
+        match Url::parse(&s) {
+            Ok(v) => Ok(v),
+            Err(e) => Err(Error::new(ErrorKind::Other, e)),
+        }
+    }
+}

+ 0 - 40
src/serial/src/types/x25519.rs

@@ -1,40 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::io::{Error, Read, Write};
-
-use x25519_dalek::PublicKey as X25519PublicKey;
-
-use crate::{Decodable, Encodable, ReadExt, WriteExt};
-
-impl Encodable for X25519PublicKey {
-    #[inline]
-    fn encode<S: Write>(&self, mut s: S) -> Result<usize, Error> {
-        s.write_slice(self.as_bytes())?;
-        Ok(32)
-    }
-}
-
-impl Decodable for X25519PublicKey {
-    #[inline]
-    fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
-        let mut bytes = [0u8; 32];
-        d.read_slice(&mut bytes)?;
-        Ok(Self::from(bytes))
-    }
-}