parent
677d4a245c
commit
efb1690872
@ -15,6 +15,8 @@ futures = "0.3"
|
|||||||
raptorq = { version = "1.7", optional = true }
|
raptorq = { version = "1.7", optional = true }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
bincode = "1.3"
|
||||||
|
once_cell = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
4
nomos-core/src/account.rs
Normal file
4
nomos-core/src/account.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct AccountId;
|
@ -1,2 +1,3 @@
|
|||||||
pub type PublicKey = [u8; 32];
|
pub type PublicKey = [u8; 32];
|
||||||
pub type PrivateKey = [u8; 32];
|
pub type PrivateKey = [u8; 32];
|
||||||
|
pub type Signature = [u8; 32];
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
pub mod account;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod fountain;
|
pub mod fountain;
|
||||||
pub mod staking;
|
pub mod staking;
|
||||||
pub mod tx;
|
pub mod tx;
|
||||||
|
pub mod wire;
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Tx;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Id;
|
|
8
nomos-core/src/tx/mod.rs
Normal file
8
nomos-core/src/tx/mod.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
mod transaction;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
pub use transaction::Transaction;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum Tx {
|
||||||
|
Transfer(Transaction),
|
||||||
|
}
|
71
nomos-core/src/tx/transaction.rs
Normal file
71
nomos-core/src/tx/transaction.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use crate::account::AccountId;
|
||||||
|
use crate::crypto::Signature;
|
||||||
|
|
||||||
|
/// Verified transactions
|
||||||
|
///
|
||||||
|
/// Can only be constructed if the signature is valid,
|
||||||
|
/// but does not imply that it can be successfully applied
|
||||||
|
/// to the ledger.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Transaction {
|
||||||
|
pub from: AccountId,
|
||||||
|
pub to: AccountId,
|
||||||
|
pub value: u64,
|
||||||
|
// TODO: here for the moment because I still want to retain the ability
|
||||||
|
// to go from `Transaction` to wire format. We could otherwise
|
||||||
|
// save the id and rely on some storage
|
||||||
|
_signature: Signature,
|
||||||
|
}
|
||||||
|
|
||||||
|
mod serde {
|
||||||
|
use super::*;
|
||||||
|
use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
// We have this additional definition so that we can automatically derive
|
||||||
|
// Serialize/Deserialize for the type while still being able to check
|
||||||
|
// the signature while deserializing.
|
||||||
|
// This would also allow to control ser/de independently from the Rust
|
||||||
|
// representation.
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct WireTransaction {
|
||||||
|
from: AccountId,
|
||||||
|
to: AccountId,
|
||||||
|
value: u64,
|
||||||
|
signature: Signature,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Transaction {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let WireTransaction {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
|
signature,
|
||||||
|
} = WireTransaction::deserialize(deserializer)?;
|
||||||
|
//TODO: check signature
|
||||||
|
Ok(Transaction {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
|
_signature: signature,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Transaction {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
WireTransaction {
|
||||||
|
from: self.from.clone(),
|
||||||
|
to: self.to.clone(),
|
||||||
|
value: self.value,
|
||||||
|
signature: self._signature,
|
||||||
|
}
|
||||||
|
.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
150
nomos-core/src/wire.rs
Normal file
150
nomos-core/src/wire.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
//! Serializer and Deserializer for wire formats.
|
||||||
|
|
||||||
|
// TODO: we're using bincode for now, but might need strong guarantees about
|
||||||
|
// the underlying format in the future for standardization.
|
||||||
|
use bincode::{
|
||||||
|
config::{
|
||||||
|
Bounded, DefaultOptions, FixintEncoding, LittleEndian, RejectTrailing, WithOtherEndian,
|
||||||
|
WithOtherIntEncoding, WithOtherLimit, WithOtherTrailing,
|
||||||
|
},
|
||||||
|
de::read::SliceReader,
|
||||||
|
Options,
|
||||||
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub type Error = bincode::Error;
|
||||||
|
// type composition is cool but also makes naming types a bit akward
|
||||||
|
type BincodeOptions = WithOtherTrailing<
|
||||||
|
WithOtherIntEncoding<
|
||||||
|
WithOtherLimit<WithOtherEndian<DefaultOptions, LittleEndian>, Bounded>,
|
||||||
|
FixintEncoding,
|
||||||
|
>,
|
||||||
|
RejectTrailing,
|
||||||
|
>;
|
||||||
|
|
||||||
|
const DATA_LIMIT: u64 = 2048; // Do not serialize/deserialize more than 2Kb
|
||||||
|
static OPTIONS: Lazy<BincodeOptions> = Lazy::new(|| {
|
||||||
|
bincode::DefaultOptions::new()
|
||||||
|
.with_little_endian()
|
||||||
|
.with_limit(DATA_LIMIT)
|
||||||
|
.with_fixint_encoding()
|
||||||
|
.reject_trailing_bytes()
|
||||||
|
});
|
||||||
|
|
||||||
|
type BincodeDeserializer<'de> = bincode::Deserializer<SliceReader<'de>, BincodeOptions>;
|
||||||
|
type BincodeSerializer<T> = bincode::Serializer<T, BincodeOptions>;
|
||||||
|
|
||||||
|
pub struct Deserializer<'de> {
|
||||||
|
inner: BincodeDeserializer<'de>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Serializer<T> {
|
||||||
|
inner: BincodeSerializer<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserializer<'de> {
|
||||||
|
pub fn get_deserializer(&mut self) -> impl serde::Deserializer<'de> + '_ {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<T: Deserialize<'de>>(&mut self) -> Result<T, Error> {
|
||||||
|
<T>::deserialize(&mut self.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::io::Write> Serializer<T> {
|
||||||
|
pub fn get_serializer(&mut self) -> impl serde::Serializer + '_ {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialize_into<U: Serialize>(
|
||||||
|
&mut self,
|
||||||
|
item: &U,
|
||||||
|
) -> Result<<&mut BincodeSerializer<T> as serde::Serializer>::Ok, Error> {
|
||||||
|
item.serialize(&mut self.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a deserializer for wire format
|
||||||
|
///
|
||||||
|
/// We only operator on in-memory slices as to abstract
|
||||||
|
/// any underlying protocol. See https://sans-io.readthedocs.io/how-to-sans-io.html
|
||||||
|
pub fn deserializer(data: &[u8]) -> Deserializer<'_> {
|
||||||
|
Deserializer {
|
||||||
|
inner: bincode::de::Deserializer::from_slice(data, *OPTIONS),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a serializer for wire format.
|
||||||
|
///
|
||||||
|
/// We only operator on in-memory slices as to abstract
|
||||||
|
/// any underlying protocol. See https://sans-io.readthedocs.io/how-to-sans-io.html
|
||||||
|
pub fn serializer(buffer: &mut Vec<u8>) -> Serializer<&'_ mut Vec<u8>> {
|
||||||
|
Serializer {
|
||||||
|
inner: bincode::Serializer::new(buffer, *OPTIONS),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a serializer for wire format that overwrites (but now grow) the provided
|
||||||
|
/// buffer.
|
||||||
|
///
|
||||||
|
/// We only operator on in-memory slices as to abstract
|
||||||
|
/// any underlying protocol. See https://sans-io.readthedocs.io/how-to-sans-io.html
|
||||||
|
pub fn serializer_into_buffer(buffer: &mut [u8]) -> Serializer<&'_ mut [u8]> {
|
||||||
|
Serializer {
|
||||||
|
inner: bincode::Serializer::new(buffer, *OPTIONS),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialize an object directly into a vec
|
||||||
|
pub fn serialize<T: Serialize>(item: &T) -> Result<Vec<u8>, Error> {
|
||||||
|
let size = OPTIONS.serialized_size(item)?;
|
||||||
|
let mut buf = Vec::with_capacity(size as usize);
|
||||||
|
serializer(&mut buf).serialize_into(item)?;
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ser_de() {
|
||||||
|
let tmp = String::from("much wow, very cool");
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let _ = serializer(&mut buf).serialize_into(&tmp).unwrap();
|
||||||
|
let deserialized = deserializer(&buf).deserialize::<String>().unwrap();
|
||||||
|
assert_eq!(tmp, deserialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ser_de_slice() {
|
||||||
|
let tmp = String::from("much wow, very cool");
|
||||||
|
let mut buf = vec![0; 1024];
|
||||||
|
let _ = serializer_into_buffer(&mut buf)
|
||||||
|
.serialize_into(&tmp)
|
||||||
|
.unwrap();
|
||||||
|
let deserialized = deserializer(&buf).deserialize::<String>().unwrap();
|
||||||
|
assert_eq!(tmp, deserialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ser_de_owned() {
|
||||||
|
let tmp = String::from("much wow, very cool");
|
||||||
|
let serialized = serialize(&tmp).unwrap();
|
||||||
|
let deserialized = deserializer(&serialized).deserialize::<String>().unwrap();
|
||||||
|
assert_eq!(tmp, deserialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ser_de_inner() {
|
||||||
|
let tmp = String::from("much wow, very cool");
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let mut serializer = serializer(&mut buf);
|
||||||
|
tmp.serialize(serializer.get_serializer()).unwrap();
|
||||||
|
let mut deserializer = deserializer(&buf);
|
||||||
|
let deserialized = <String>::deserialize(deserializer.get_deserializer()).unwrap();
|
||||||
|
assert_eq!(tmp, deserialized);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user