Skip to content

Commit

Permalink
feat(primitives): Enable serde of ledger structs (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
scarmuega authored Aug 12, 2022
1 parent f29cc64 commit 2e95b7b
Show file tree
Hide file tree
Showing 22 changed files with 584 additions and 270 deletions.
10 changes: 5 additions & 5 deletions pallas-addresses/src/byron.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub type Blake2b224 = Hash<28>;
pub type AddressId = Blake2b224;
pub type StakeholderId = Blake2b224;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum AddrDistr {
Variant0(StakeholderId),
Variant1,
Expand Down Expand Up @@ -57,7 +57,7 @@ impl minicbor::Encode<()> for AddrDistr {
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum AddrType {
PubKey,
Script,
Expand Down Expand Up @@ -98,7 +98,7 @@ impl<C> minicbor::Encode<C> for AddrType {
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum AddrAttrProperty {
AddrDistr(AddrDistr),
Bytes(ByteVec),
Expand Down Expand Up @@ -148,7 +148,7 @@ impl<C> minicbor::Encode<C> for AddrAttrProperty {

pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;

#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd)]
pub struct AddressPayload {
#[n(0)]
pub root: AddressId,
Expand All @@ -161,7 +161,7 @@ pub struct AddressPayload {
}

/// New type wrapping a Byron address primitive
#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ByronAddress {
#[n(0)]
payload: TagWrap<ByteVec, 24>,
Expand Down
18 changes: 9 additions & 9 deletions pallas-addresses/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub type TxIdx = u64;
pub type CertIdx = u64;

/// An on-chain pointer to a stake key
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Pointer(Slot, TxIdx, CertIdx);

fn slice_to_hash(slice: &[u8]) -> Result<Hash<28>, Error> {
Expand Down Expand Up @@ -113,7 +113,7 @@ impl Pointer {
}

/// The payment part of a Shelley address
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
pub enum ShelleyPaymentPart {
Key(PaymentKeyHash),
Script(ScriptHash),
Expand Down Expand Up @@ -151,7 +151,7 @@ impl ShelleyPaymentPart {
}

/// The delegation part of a Shelley address
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
pub enum ShelleyDelegationPart {
Key(StakeKeyHash),
Script(ScriptHash),
Expand Down Expand Up @@ -212,7 +212,7 @@ impl StakePayload {
}

/// The network tag of an address
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
pub enum Network {
Testnet,
Mainnet,
Expand All @@ -230,24 +230,24 @@ impl From<u8> for Network {
}

/// A decoded Shelley address
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
pub struct ShelleyAddress(Network, ShelleyPaymentPart, ShelleyDelegationPart);

/// The payload of a Stake address
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
pub enum StakePayload {
Stake(StakeKeyHash),
Script(ScriptHash),
}

/// A decoded Stake address
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
pub struct StakeAddress(Network, StakePayload);

pub use byron::ByronAddress;

/// A decoded Cardano address of any type
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
pub enum Address {
Byron(ByronAddress),
Shelley(ShelleyAddress),
Expand Down Expand Up @@ -345,7 +345,7 @@ parse_stake_fn!(parse_type_14, stake_key);
parse_stake_fn!(parse_type_15, script);

fn bytes_to_address(bytes: &[u8]) -> Result<Address, Error> {
let header = *bytes.get(0).ok_or(Error::MissingHeader)?;
let header = *bytes.first().ok_or(Error::MissingHeader)?;
let payload = &bytes[1..];

match header & 0b1111_0000 {
Expand Down
2 changes: 2 additions & 0 deletions pallas-codec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ authors = [
]

[dependencies]
hex = "0.4.3"
minicbor = { version = "0.17", features = ["std", "half", "derive"] }
serde = { version = "1.0.143", features = ["derive"] }

170 changes: 159 additions & 11 deletions pallas-codec/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::Deref;

use minicbor::{data::Tag, Decode, Encode};
use serde::{Deserialize, Serialize};
use std::ops::Deref;

/// Utility for skipping parts of the CBOR payload, use only for debugging
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
Expand Down Expand Up @@ -43,6 +43,21 @@ pub enum KeyValuePairs<K, V> {
Indef(Vec<(K, V)>),
}

impl<K, V> KeyValuePairs<K, V> {
pub fn to_vec(self) -> Vec<(K, V)> {
self.into()
}
}

impl<K, V> From<KeyValuePairs<K, V>> for Vec<(K, V)> {
fn from(other: KeyValuePairs<K, V>) -> Self {
match other {
KeyValuePairs::Def(x) => x,
KeyValuePairs::Indef(x) => x,
}
}
}

impl<K, V> Deref for KeyValuePairs<K, V> {
type Target = Vec<(K, V)>;

Expand Down Expand Up @@ -117,6 +132,12 @@ pub enum MaybeIndefArray<A> {
Indef(Vec<A>),
}

impl<A> MaybeIndefArray<A> {
pub fn to_vec(self) -> Vec<A> {
self.into()
}
}

impl<A> Deref for MaybeIndefArray<A> {
type Target = Vec<A>;

Expand All @@ -128,6 +149,15 @@ impl<A> Deref for MaybeIndefArray<A> {
}
}

impl<A> From<MaybeIndefArray<A>> for Vec<A> {
fn from(other: MaybeIndefArray<A>) -> Self {
match other {
MaybeIndefArray::Def(x) => x,
MaybeIndefArray::Indef(x) => x,
}
}
}

impl<'b, C, A> minicbor::decode::Decode<'b, C> for MaybeIndefArray<A>
where
A: minicbor::decode::Decode<'b, C>,
Expand Down Expand Up @@ -186,7 +216,7 @@ where
/// transform key-value structures into an orderer vec of `properties`, where
/// each entry represents a a cbor-encodable variant of an attribute of the
/// struct.
#[derive(Debug, PartialEq, Clone, PartialOrd)]
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]
pub struct OrderPreservingProperties<P>(Vec<P>);

impl<P> Deref for OrderPreservingProperties<P> {
Expand Down Expand Up @@ -229,7 +259,8 @@ where
}

/// Wraps a struct so that it is encoded/decoded as a cbor bytes
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd)]
#[serde(transparent)]
pub struct CborWrap<T>(pub T);

impl<'b, C, T> minicbor::Decode<'b, C> for CborWrap<T>
Expand Down Expand Up @@ -273,7 +304,7 @@ impl<T> Deref for CborWrap<T> {
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct TagWrap<I, const T: u64>(pub I);

impl<I, const T: u64> TagWrap<I, T> {
Expand Down Expand Up @@ -526,7 +557,7 @@ impl From<&AnyUInt> for u64 {
/// let confirm: (u16, u16) = minicbor::decode(keeper.raw_cbor()).unwrap();
/// assert_eq!(confirm, (456u16, 789u16));
/// ```
#[derive(Debug, PartialEq, PartialOrd, Clone)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct KeepRaw<'b, T> {
raw: &'b [u8],
inner: T,
Expand All @@ -536,6 +567,10 @@ impl<'b, T> KeepRaw<'b, T> {
pub fn raw_cbor(&self) -> &'b [u8] {
self.raw
}

pub fn unwrap(self) -> T {
self.inner
}
}

impl<'b, T> Deref for KeepRaw<'b, T> {
Expand Down Expand Up @@ -575,16 +610,37 @@ impl<C, T> minicbor::Encode<C> for KeepRaw<'_, T> {
}
}

#[derive(Clone, Debug)]
pub enum Nullable<T> {
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(from = "Option::<T>", into = "Option::<T>")]
pub enum Nullable<T>
where
T: std::clone::Clone,
{
Some(T),
Null,
Undefined,
}

impl<T> Nullable<T>
where
T: std::clone::Clone,
{
pub fn map<F, O>(self, f: F) -> Nullable<O>
where
O: std::clone::Clone,
F: Fn(T) -> O,
{
match self {
Nullable::Some(x) => Nullable::Some(f(x)),
Nullable::Null => Nullable::Null,
Nullable::Undefined => Nullable::Undefined,
}
}
}

impl<'b, C, T> minicbor::Decode<'b, C> for Nullable<T>
where
T: minicbor::Decode<'b, C>,
T: minicbor::Decode<'b, C> + std::clone::Clone,
{
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
match d.datatype()? {
Expand All @@ -606,7 +662,7 @@ where

impl<C, T> minicbor::Encode<C> for Nullable<T>
where
T: minicbor::Encode<C>,
T: minicbor::Encode<C> + std::clone::Clone,
{
fn encode<W: minicbor::encode::Write>(
&self,
Expand All @@ -630,11 +686,103 @@ where
}
}

impl<T> From<Option<T>> for Nullable<T> {
impl<T> From<Option<T>> for Nullable<T>
where
T: std::clone::Clone,
{
fn from(x: Option<T>) -> Self {
match x {
Some(x) => Nullable::Some(x),
None => Nullable::Null,
}
}
}

impl<T> From<Nullable<T>> for Option<T>
where
T: std::clone::Clone,
{
fn from(other: Nullable<T>) -> Self {
match other {
Nullable::Some(x) => Some(x),
_ => None,
}
}
}

#[derive(Serialize, Deserialize, Clone, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cbor(transparent)]
#[serde(into = "String")]
#[serde(try_from = "String")]
pub struct Bytes(#[n(0)] minicbor::bytes::ByteVec);

impl From<Vec<u8>> for Bytes {
fn from(xs: Vec<u8>) -> Self {
Bytes(minicbor::bytes::ByteVec::from(xs))
}
}

impl From<Bytes> for Vec<u8> {
fn from(b: Bytes) -> Self {
b.0.into()
}
}

impl Deref for Bytes {
type Target = Vec<u8>;

fn deref(&self) -> &Self::Target {
self.0.deref()
}
}

impl TryFrom<String> for Bytes {
type Error = hex::FromHexError;

fn try_from(value: String) -> Result<Self, Self::Error> {
let v = hex::decode(value)?;
Ok(Bytes(minicbor::bytes::ByteVec::from(v)))
}
}

impl From<Bytes> for String {
fn from(b: Bytes) -> Self {
hex::encode(b.deref())
}
}

#[derive(Serialize, Deserialize, Clone, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cbor(transparent)]
#[serde(into = "i128")]
#[serde(try_from = "i128")]
pub struct Int(#[n(0)] pub minicbor::data::Int);

impl Deref for Int {
type Target = minicbor::data::Int;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<Int> for i128 {
fn from(value: Int) -> Self {
i128::from(value.0)
}
}

impl From<i64> for Int {
fn from(x: i64) -> Self {
let inner = minicbor::data::Int::from(x);
Self(inner)
}
}

impl TryFrom<i128> for Int {
type Error = minicbor::data::TryFromIntError;

fn try_from(value: i128) -> Result<Self, Self::Error> {
let inner = minicbor::data::Int::try_from(value)?;
Ok(Self(inner))
}
}
Loading

0 comments on commit 2e95b7b

Please sign in to comment.