feat(traverse): Add era-handling utilities (#123)

This commit is contained in:
Santiago Carmuega 2022-06-17 05:19:12 -03:00 committed by GitHub
parent 74e05dddca
commit f708c9c687
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 13 deletions

View file

@ -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()

View file

@ -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,
}
}
}

View file

@ -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(),
}
}
}

View file

@ -3,6 +3,7 @@
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;
@ -10,6 +11,7 @@ use thiserror::Error;
pub mod block;
pub mod cert;
pub mod era;
pub mod header;
pub mod input;
pub mod output;
pub mod probe;
@ -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> {
@ -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>>>),
}
@ -78,6 +87,9 @@ pub enum Error {
#[error("Unknown CBOR structure: {0}")]
UnknownCbor(String),
#[error("Unknown era tag: {0}")]
UnkownEra(u16),
}
impl Error {

View file

@ -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()
@ -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()
@ -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()
@ -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),
}
}