Skip to content

Commit

Permalink
feat(traverse): Add era-handling utilities (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
scarmuega authored Jun 17, 2022
1 parent 74e05dd commit f708c9c
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 13 deletions.
4 changes: 2 additions & 2 deletions pallas-traverse/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ impl<'b> MultiEraBlock<'b> {

pub fn txs(&self) -> Vec<MultiEraTx> {
match self {
MultiEraBlock::AlonzoCompatible(x, _) => support::clone_alonzo_txs(x)
MultiEraBlock::AlonzoCompatible(x, era) => support::clone_alonzo_txs(x)
.into_iter()
.map(|x| MultiEraTx::AlonzoCompatible(Box::new(Cow::Owned(x))))
.map(|x| MultiEraTx::AlonzoCompatible(Box::new(Cow::Owned(x)), *era))
.collect(),
MultiEraBlock::Byron(x) => support::clone_byron_txs(x)
.into_iter()
Expand Down
30 changes: 30 additions & 0 deletions pallas-traverse/src/era.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,33 @@ impl Era {
}
}
}

// for consistency, we use the same tag convention used by the node's cbor
// encoding
impl TryFrom<u16> for Era {
type Error = crate::Error;

fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0 => Ok(Era::Byron),
1 => Ok(Era::Byron),
2 => Ok(Era::Shelley),
3 => Ok(Era::Allegra),
4 => Ok(Era::Mary),
5 => Ok(Era::Alonzo),
x => Err(crate::Error::UnkownEra(x)),
}
}
}

impl From<Era> for u16 {
fn from(other: Era) -> Self {
match other {
Era::Byron => 1,
Era::Shelley => 2,
Era::Allegra => 3,
Era::Mary => 4,
Era::Alonzo => 5,
}
}
}
42 changes: 42 additions & 0 deletions pallas-traverse/src/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use pallas_codec::minicbor;
use pallas_crypto::hash::Hash;
use pallas_primitives::ToHash;

use crate::{Error, MultiEraHeader};

impl<'b> MultiEraHeader<'b> {
pub fn decode(tag: u8, subtag: Option<u8>, cbor: &'b [u8]) -> Result<Self, Error> {
match tag {
0 => match subtag {
Some(0) => {
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
Ok(MultiEraHeader::EpochBoundary(header))
}
_ => {
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
Ok(MultiEraHeader::Byron(header))
}
},
_ => {
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
Ok(MultiEraHeader::AlonzoCompatible(header))
}
}
}

pub fn slot(&self) -> u64 {
match self {
MultiEraHeader::EpochBoundary(x) => x.to_abs_slot(),
MultiEraHeader::AlonzoCompatible(x) => x.header_body.slot,
MultiEraHeader::Byron(x) => x.consensus_data.0.to_abs_slot(),
}
}

pub fn hash(&self) -> Hash<32> {
match self {
MultiEraHeader::EpochBoundary(x) => x.to_hash(),
MultiEraHeader::AlonzoCompatible(x) => x.to_hash(),
MultiEraHeader::Byron(x) => x.to_hash(),
}
}
}
14 changes: 13 additions & 1 deletion pallas-traverse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
use std::borrow::Cow;
use std::fmt::Display;

use pallas_codec::utils::KeepRaw;
use pallas_crypto::hash::Hash;
use pallas_primitives::{alonzo, byron};
use thiserror::Error;

pub mod block;
pub mod cert;
pub mod era;
pub mod header;
pub mod input;
pub mod output;
pub mod probe;
Expand All @@ -35,6 +37,13 @@ pub enum Feature {
SmartContracts,
}

#[derive(Debug)]
pub enum MultiEraHeader<'b> {
EpochBoundary(KeepRaw<'b, byron::EbbHead>),
AlonzoCompatible(KeepRaw<'b, alonzo::Header>),
Byron(KeepRaw<'b, byron::BlockHead>),
}

#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum MultiEraBlock<'b> {
Expand All @@ -46,7 +55,7 @@ pub enum MultiEraBlock<'b> {
#[derive(Debug)]
#[non_exhaustive]
pub enum MultiEraTx<'b> {
AlonzoCompatible(Box<Cow<'b, alonzo::MintedTx<'b>>>),
AlonzoCompatible(Box<Cow<'b, alonzo::MintedTx<'b>>>, Era),
Byron(Box<Cow<'b, byron::MintedTxPayload<'b>>>),
}

Expand Down Expand Up @@ -78,6 +87,9 @@ pub enum Error {

#[error("Unknown CBOR structure: {0}")]
UnknownCbor(String),

#[error("Unknown era tag: {0}")]
UnkownEra(u16),
}

impl Error {
Expand Down
42 changes: 32 additions & 10 deletions pallas-traverse/src/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,56 @@ use pallas_crypto::hash::Hash;
use pallas_primitives::{alonzo, byron, ToHash};
use std::borrow::Cow;

use crate::{MultiEraCert, MultiEraInput, MultiEraOutput, MultiEraTx};
use crate::{Era, MultiEraCert, MultiEraInput, MultiEraOutput, MultiEraTx};

impl<'b> MultiEraTx<'b> {
pub fn from_byron(tx: &'b byron::MintedTxPayload<'b>) -> Self {
Self::Byron(Box::new(Cow::Borrowed(tx)))
}

pub fn from_alonzo_compatible(tx: &'b alonzo::MintedTx<'b>) -> Self {
Self::AlonzoCompatible(Box::new(Cow::Borrowed(tx)))
pub fn from_alonzo_compatible(tx: &'b alonzo::MintedTx<'b>, era: Era) -> Self {
Self::AlonzoCompatible(Box::new(Cow::Borrowed(tx)), era)
}

pub fn encode(&self) -> Result<Vec<u8>, minicbor::encode::Error<std::io::Error>> {
match self {
MultiEraTx::AlonzoCompatible(x) => minicbor::to_vec(x),
MultiEraTx::AlonzoCompatible(x, _) => minicbor::to_vec(x),
MultiEraTx::Byron(x) => minicbor::to_vec(x),
}
}

pub fn decode(era: Era, cbor: &'b [u8]) -> Result<Self, minicbor::decode::Error> {
match era {
Era::Byron => {
let tx = minicbor::decode(cbor)?;
let tx = Box::new(Cow::Owned(tx));
Ok(MultiEraTx::Byron(tx))
}
Era::Shelley | Era::Allegra | Era::Mary | Era::Alonzo => {
let tx = minicbor::decode(cbor)?;
let tx = Box::new(Cow::Owned(tx));
Ok(MultiEraTx::AlonzoCompatible(tx, era))
}
}
}

pub fn era(&self) -> Era {
match self {
MultiEraTx::AlonzoCompatible(_, era) => *era,
MultiEraTx::Byron(_) => Era::Byron,
}
}

pub fn hash(&self) -> Hash<32> {
match self {
MultiEraTx::AlonzoCompatible(x) => x.transaction_body.to_hash(),
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.to_hash(),
MultiEraTx::Byron(x) => x.transaction.to_hash(),
}
}

pub fn outputs(&self) -> Vec<MultiEraOutput> {
match self {
MultiEraTx::AlonzoCompatible(x) => x
MultiEraTx::AlonzoCompatible(x, _) => x
.transaction_body
.outputs
.iter()
Expand All @@ -47,7 +69,7 @@ impl<'b> MultiEraTx<'b> {

pub fn inputs(&self) -> Vec<MultiEraInput> {
match self {
MultiEraTx::AlonzoCompatible(x) => x
MultiEraTx::AlonzoCompatible(x, _) => x
.transaction_body
.inputs
.iter()
Expand All @@ -65,7 +87,7 @@ impl<'b> MultiEraTx<'b> {

pub fn certs(&self) -> Vec<MultiEraCert> {
match self {
MultiEraTx::AlonzoCompatible(x) => x
MultiEraTx::AlonzoCompatible(x, _) => x
.transaction_body
.certificates
.iter()
Expand All @@ -78,14 +100,14 @@ impl<'b> MultiEraTx<'b> {

pub fn as_alonzo(&self) -> Option<&alonzo::MintedTx> {
match self {
MultiEraTx::AlonzoCompatible(x) => Some(x),
MultiEraTx::AlonzoCompatible(x, _) => Some(x),
MultiEraTx::Byron(_) => None,
}
}

pub fn as_byron(&self) -> Option<&byron::MintedTxPayload> {
match self {
MultiEraTx::AlonzoCompatible(_) => None,
MultiEraTx::AlonzoCompatible(_, _) => None,
MultiEraTx::Byron(x) => Some(x),
}
}
Expand Down

0 comments on commit f708c9c

Please sign in to comment.