feat(traverse): Introduce new accessor methods (#152)
This commit is contained in:
parent
3b685e8b7f
commit
3ac707e486
17 changed files with 507 additions and 238 deletions
|
|
@ -16,7 +16,6 @@ authors = [
|
|||
hex = "0.4.3"
|
||||
pallas-crypto = { version = "0.11.0", path = "../pallas-crypto" }
|
||||
pallas-codec = { version = "0.11.0", path = "../pallas-codec" }
|
||||
pallas-primitives = { version = "0.11.0", path = "../pallas-primitives" }
|
||||
base58 = "0.2.0"
|
||||
bech32 = "0.8.1"
|
||||
thiserror = "1.0.31"
|
||||
|
|
|
|||
159
pallas-addresses/src/byron.rs
Normal file
159
pallas-addresses/src/byron.rs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
use pallas_codec::{
|
||||
minicbor::{self, bytes::ByteVec, Decode, Encode},
|
||||
utils::OrderPreservingProperties,
|
||||
};
|
||||
|
||||
use pallas_crypto::hash::Hash;
|
||||
|
||||
pub type Blake2b224 = Hash<28>;
|
||||
|
||||
pub type AddressId = Blake2b224;
|
||||
pub type StakeholderId = Blake2b224;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub enum AddrDistr {
|
||||
Variant0(StakeholderId),
|
||||
Variant1,
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::Decode<'b, C> for AddrDistr {
|
||||
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||
d.array()?;
|
||||
let variant = d.u32()?;
|
||||
|
||||
match variant {
|
||||
0 => Ok(AddrDistr::Variant0(d.decode_with(ctx)?)),
|
||||
1 => Ok(AddrDistr::Variant1),
|
||||
_ => Err(minicbor::decode::Error::message(
|
||||
"invalid variant for addrdstr",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl minicbor::Encode<()> for AddrDistr {
|
||||
fn encode<W: minicbor::encode::Write>(
|
||||
&self,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
_ctx: &mut (),
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
match self {
|
||||
AddrDistr::Variant0(x) => {
|
||||
e.array(2)?;
|
||||
e.u32(0)?;
|
||||
e.encode(x)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AddrDistr::Variant1 => {
|
||||
e.array(1)?;
|
||||
e.u32(1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub enum AddrType {
|
||||
PubKey,
|
||||
Script,
|
||||
Redeem,
|
||||
Other(u64),
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::Decode<'b, C> for AddrType {
|
||||
fn decode(
|
||||
d: &mut minicbor::Decoder<'b>,
|
||||
_ctx: &mut C,
|
||||
) -> Result<Self, minicbor::decode::Error> {
|
||||
let variant = d.u64()?;
|
||||
|
||||
match variant {
|
||||
0 => Ok(AddrType::PubKey),
|
||||
1 => Ok(AddrType::Script),
|
||||
2 => Ok(AddrType::Redeem),
|
||||
x => Ok(AddrType::Other(x)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> minicbor::Encode<C> for AddrType {
|
||||
fn encode<W: minicbor::encode::Write>(
|
||||
&self,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
_ctx: &mut C,
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
match self {
|
||||
AddrType::PubKey => e.u64(0)?,
|
||||
AddrType::Script => e.u64(1)?,
|
||||
AddrType::Redeem => e.u64(2)?,
|
||||
AddrType::Other(x) => e.u64(*x)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub enum AddrAttrProperty {
|
||||
AddrDistr(AddrDistr),
|
||||
Bytes(ByteVec),
|
||||
Unparsed(u8, ByteVec),
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::Decode<'b, C> for AddrAttrProperty {
|
||||
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||
let key = d.u8()?;
|
||||
|
||||
match key {
|
||||
0 => Ok(AddrAttrProperty::AddrDistr(d.decode_with(ctx)?)),
|
||||
1 => Ok(AddrAttrProperty::Bytes(d.decode_with(ctx)?)),
|
||||
x => Ok(AddrAttrProperty::Unparsed(x, d.decode_with(ctx)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> minicbor::Encode<C> for AddrAttrProperty {
|
||||
fn encode<W: minicbor::encode::Write>(
|
||||
&self,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
_ctx: &mut C,
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
match self {
|
||||
AddrAttrProperty::AddrDistr(x) => {
|
||||
e.u32(0)?;
|
||||
e.encode(x)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AddrAttrProperty::Bytes(x) => {
|
||||
e.u32(1)?;
|
||||
e.encode(x)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AddrAttrProperty::Unparsed(a, b) => {
|
||||
e.encode(a)?;
|
||||
e.encode(b)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;
|
||||
|
||||
#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)]
|
||||
pub struct AddressPayload {
|
||||
#[n(0)]
|
||||
pub root: AddressId,
|
||||
|
||||
#[n(1)]
|
||||
pub attributes: AddrAttr,
|
||||
|
||||
#[n(2)]
|
||||
pub addrtype: AddrType,
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
//!
|
||||
//! For more information regarding Cardano addresses and their formats, please refer to [CIP-19](https://cips.cardano.org/cips/cip19/).
|
||||
|
||||
pub mod byron;
|
||||
pub mod varuint;
|
||||
|
||||
use std::io::Cursor;
|
||||
|
|
@ -236,10 +237,10 @@ pub struct StakeAddress(Network, StakePayload);
|
|||
|
||||
/// New type wrapping a Byron address primitive
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub struct ByronAddress(pallas_primitives::byron::Address);
|
||||
pub struct ByronAddress(byron::AddressPayload);
|
||||
|
||||
impl ByronAddress {
|
||||
pub fn new(primitive: pallas_primitives::byron::Address) -> Self {
|
||||
pub fn new(primitive: byron::AddressPayload) -> Self {
|
||||
Self(primitive)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ impl<T> Deref for CborWrap<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub struct TagWrap<I, const T: u64>(I);
|
||||
|
||||
impl<I, const T: u64> TagWrap<I, T> {
|
||||
|
|
@ -309,6 +309,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<I, const T: u64> Deref for TagWrap<I, T> {
|
||||
type Target = I;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// An empty map
|
||||
///
|
||||
/// don't ask me why, that's what the CDDL asks for.
|
||||
|
|
|
|||
|
|
@ -4,12 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use log::info;
|
||||
use pallas_codec::minicbor;
|
||||
use pallas_multiplexer::{
|
||||
agents::{Channel, ChannelBuffer},
|
||||
bearers::Bearer,
|
||||
Payload, StdPlexer,
|
||||
};
|
||||
use pallas_multiplexer::{agents::Channel, bearers::Bearer, StdPlexer};
|
||||
use rand::{distributions::Uniform, Rng};
|
||||
|
||||
fn setup_passive_muxer<const P: u16>() -> JoinHandle<StdPlexer> {
|
||||
|
|
|
|||
|
|
@ -280,6 +280,8 @@ pub struct MoveInstantaneousReward {
|
|||
|
||||
pub type RewardAccount = ByteVec;
|
||||
|
||||
pub type Withdrawals = KeyValuePairs<RewardAccount, Coin>;
|
||||
|
||||
pub type Port = u32;
|
||||
pub type IPv4 = ByteVec;
|
||||
pub type IPv6 = ByteVec;
|
||||
|
|
@ -719,7 +721,7 @@ pub struct TransactionBody {
|
|||
pub certificates: Option<MaybeIndefArray<Certificate>>,
|
||||
|
||||
#[n(5)]
|
||||
pub withdrawals: Option<KeyValuePairs<RewardAccount, Coin>>,
|
||||
pub withdrawals: Option<Withdrawals>,
|
||||
|
||||
#[n(6)]
|
||||
pub update: Option<Update>,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use pallas_codec::minicbor::{bytes::ByteVec, Decode, Encode};
|
|||
use pallas_crypto::hash::Hash;
|
||||
|
||||
use pallas_codec::utils::{
|
||||
CborWrap, EmptyMap, KeepRaw, KeyValuePairs, MaybeIndefArray, OrderPreservingProperties,
|
||||
TagWrap, ZeroOrOneArray,
|
||||
CborWrap, EmptyMap, KeepRaw, KeyValuePairs, MaybeIndefArray, TagWrap, ZeroOrOneArray,
|
||||
};
|
||||
|
||||
// required for derive attrs to work
|
||||
|
|
@ -49,161 +48,14 @@ pub type Signature = ByteVec;
|
|||
// attributes = {* any => any}
|
||||
pub type Attributes = EmptyMap;
|
||||
|
||||
// Addresses
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub enum AddrDistr {
|
||||
Variant0(StakeholderId),
|
||||
Variant1,
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::Decode<'b, C> for AddrDistr {
|
||||
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||
d.array()?;
|
||||
let variant = d.u32()?;
|
||||
|
||||
match variant {
|
||||
0 => Ok(AddrDistr::Variant0(d.decode_with(ctx)?)),
|
||||
1 => Ok(AddrDistr::Variant1),
|
||||
_ => Err(minicbor::decode::Error::message(
|
||||
"invalid variant for addrdstr",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl minicbor::Encode<()> for AddrDistr {
|
||||
fn encode<W: minicbor::encode::Write>(
|
||||
&self,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
_ctx: &mut (),
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
match self {
|
||||
AddrDistr::Variant0(x) => {
|
||||
e.array(2)?;
|
||||
e.u32(0)?;
|
||||
e.encode(x)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AddrDistr::Variant1 => {
|
||||
e.array(1)?;
|
||||
e.u32(1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub enum AddrType {
|
||||
PubKey,
|
||||
Script,
|
||||
Redeem,
|
||||
Other(u64),
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::Decode<'b, C> for AddrType {
|
||||
fn decode(
|
||||
d: &mut minicbor::Decoder<'b>,
|
||||
_ctx: &mut C,
|
||||
) -> Result<Self, minicbor::decode::Error> {
|
||||
let variant = d.u64()?;
|
||||
|
||||
match variant {
|
||||
0 => Ok(AddrType::PubKey),
|
||||
1 => Ok(AddrType::Script),
|
||||
2 => Ok(AddrType::Redeem),
|
||||
x => Ok(AddrType::Other(x)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> minicbor::Encode<C> for AddrType {
|
||||
fn encode<W: minicbor::encode::Write>(
|
||||
&self,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
_ctx: &mut C,
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
match self {
|
||||
AddrType::PubKey => e.u64(0)?,
|
||||
AddrType::Script => e.u64(1)?,
|
||||
AddrType::Redeem => e.u64(2)?,
|
||||
AddrType::Other(x) => e.u64(*x)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub enum AddrAttrProperty {
|
||||
AddrDistr(AddrDistr),
|
||||
Bytes(ByteVec),
|
||||
Unparsed(u8, ByteVec),
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::Decode<'b, C> for AddrAttrProperty {
|
||||
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||
let key = d.u8()?;
|
||||
|
||||
match key {
|
||||
0 => Ok(AddrAttrProperty::AddrDistr(d.decode_with(ctx)?)),
|
||||
1 => Ok(AddrAttrProperty::Bytes(d.decode_with(ctx)?)),
|
||||
x => Ok(AddrAttrProperty::Unparsed(x, d.decode_with(ctx)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> minicbor::Encode<C> for AddrAttrProperty {
|
||||
fn encode<W: minicbor::encode::Write>(
|
||||
&self,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
_ctx: &mut C,
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
match self {
|
||||
AddrAttrProperty::AddrDistr(x) => {
|
||||
e.u32(0)?;
|
||||
e.encode(x)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AddrAttrProperty::Bytes(x) => {
|
||||
e.u32(1)?;
|
||||
e.encode(x)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AddrAttrProperty::Unparsed(a, b) => {
|
||||
e.encode(a)?;
|
||||
e.encode(b)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;
|
||||
|
||||
#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)]
|
||||
pub struct AddressPayload {
|
||||
#[n(0)]
|
||||
pub root: AddressId,
|
||||
|
||||
#[n(1)]
|
||||
pub attributes: AddrAttr,
|
||||
|
||||
#[n(2)]
|
||||
pub addrtype: AddrType,
|
||||
}
|
||||
// The cbor struct of the address payload is now defined in pallas-addresses.
|
||||
// The primitives crate will treat addresses as a black-box vec of bytes.
|
||||
|
||||
// address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ]
|
||||
#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)]
|
||||
pub struct Address {
|
||||
#[n(0)]
|
||||
pub payload: CborWrap<AddressPayload>,
|
||||
pub payload: TagWrap<ByteVec, 24>,
|
||||
|
||||
#[n(1)]
|
||||
pub crc: u64,
|
||||
|
|
@ -954,6 +806,18 @@ pub struct EbBlock {
|
|||
pub extra: MaybeIndefArray<Attributes>,
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Debug, Clone)]
|
||||
pub struct MintedEbBlock<'b> {
|
||||
#[b(0)]
|
||||
pub header: KeepRaw<'b, EbbHead>,
|
||||
|
||||
#[n(1)]
|
||||
pub body: MaybeIndefArray<StakeholderId>,
|
||||
|
||||
#[n(2)]
|
||||
pub extra: MaybeIndefArray<Attributes>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{BlockHead, EbBlock, MintedBlock};
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ use std::borrow::Cow;
|
|||
|
||||
use pallas_codec::minicbor;
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::{alonzo, babbage, byron, ToHash};
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
|
||||
use crate::{probe, support, Era, Error, MultiEraBlock, MultiEraTx};
|
||||
use crate::{probe, support, Era, Error, MultiEraBlock, MultiEraHeader, MultiEraTx};
|
||||
|
||||
type BlockWrapper<T> = (u16, T);
|
||||
|
||||
impl<'b> MultiEraBlock<'b> {
|
||||
pub fn decode_epoch_boundary(cbor: &'b [u8]) -> Result<Self, Error> {
|
||||
let (_, block): BlockWrapper<byron::EbBlock> =
|
||||
let (_, block): BlockWrapper<byron::MintedEbBlock> =
|
||||
minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||
|
||||
Ok(Self::EpochBoundary(Box::new(Cow::Owned(block))))
|
||||
|
|
@ -85,27 +85,24 @@ impl<'b> MultiEraBlock<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn number(&self) -> u64 {
|
||||
pub fn header(&self) -> MultiEraHeader<'_> {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(x) => x
|
||||
.header
|
||||
.consensus_data
|
||||
.difficulty
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => x.header.header_body.block_number,
|
||||
MultiEraBlock::Babbage(x) => x.header.header_body.block_number,
|
||||
MultiEraBlock::Byron(x) => x
|
||||
.header
|
||||
.consensus_data
|
||||
.2
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
MultiEraBlock::EpochBoundary(x) => {
|
||||
MultiEraHeader::EpochBoundary(Cow::Borrowed(&x.header))
|
||||
}
|
||||
MultiEraBlock::Byron(x) => MultiEraHeader::Byron(Cow::Borrowed(&x.header)),
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => {
|
||||
MultiEraHeader::AlonzoCompatible(Cow::Borrowed(&x.header))
|
||||
}
|
||||
MultiEraBlock::Babbage(x) => MultiEraHeader::Babbage(Cow::Borrowed(&x.header)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the block number (aka: height)
|
||||
pub fn number(&self) -> u64 {
|
||||
self.header().number()
|
||||
}
|
||||
|
||||
pub fn era(&self) -> Era {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => Era::Byron,
|
||||
|
|
@ -116,23 +113,14 @@ impl<'b> MultiEraBlock<'b> {
|
|||
}
|
||||
|
||||
pub fn hash(&self) -> Hash<32> {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(x) => x.header.to_hash(),
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => x.header.to_hash(),
|
||||
MultiEraBlock::Babbage(x) => x.header.to_hash(),
|
||||
MultiEraBlock::Byron(x) => x.header.to_hash(),
|
||||
}
|
||||
self.header().hash()
|
||||
}
|
||||
|
||||
pub fn slot(&self) -> u64 {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(x) => x.header.to_abs_slot(),
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => x.header.header_body.slot,
|
||||
MultiEraBlock::Babbage(x) => x.header.header_body.slot,
|
||||
MultiEraBlock::Byron(x) => x.header.consensus_data.0.to_abs_slot(),
|
||||
}
|
||||
self.header().slot()
|
||||
}
|
||||
|
||||
/// Builds a vec with the Txs of the block
|
||||
pub fn txs(&self) -> Vec<MultiEraTx> {
|
||||
match self {
|
||||
MultiEraBlock::AlonzoCompatible(x, era) => support::clone_alonzo_txs(x)
|
||||
|
|
@ -151,6 +139,36 @@ impl<'b> MultiEraBlock<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the there're no tx in the block
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => true,
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => x.transaction_bodies.is_empty(),
|
||||
MultiEraBlock::Babbage(x) => x.transaction_bodies.is_empty(),
|
||||
MultiEraBlock::Byron(x) => x.body.tx_payload.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the count of txs in the block
|
||||
pub fn tx_count(&self) -> usize {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => 0,
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => x.transaction_bodies.len(),
|
||||
MultiEraBlock::Babbage(x) => x.transaction_bodies.len(),
|
||||
MultiEraBlock::Byron(x) => x.body.tx_payload.len(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the block has any auxiliary data
|
||||
pub fn has_aux_data(&self) -> bool {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => false,
|
||||
MultiEraBlock::AlonzoCompatible(x, _) => !x.auxiliary_data_set.is_empty(),
|
||||
MultiEraBlock::Babbage(x) => !x.auxiliary_data_set.is_empty(),
|
||||
MultiEraBlock::Byron(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::MintedBlock> {
|
||||
match self {
|
||||
MultiEraBlock::EpochBoundary(_) => None,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use crate::MultiEraCert;
|
|||
impl<'b> MultiEraCert<'b> {
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::Certificate> {
|
||||
match self {
|
||||
MultiEraCert::NotApplicable => None,
|
||||
MultiEraCert::AlonzoCompatible(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use pallas_codec::minicbor;
|
||||
use pallas_crypto::hash::{Hash, Hasher};
|
||||
use pallas_primitives::ToHash;
|
||||
|
|
@ -11,24 +13,33 @@ impl<'b> MultiEraHeader<'b> {
|
|||
0 => match subtag {
|
||||
Some(0) => {
|
||||
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||
Ok(MultiEraHeader::EpochBoundary(header))
|
||||
Ok(MultiEraHeader::EpochBoundary(Cow::Owned(header)))
|
||||
}
|
||||
_ => {
|
||||
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||
Ok(MultiEraHeader::Byron(header))
|
||||
Ok(MultiEraHeader::Byron(Cow::Owned(header)))
|
||||
}
|
||||
},
|
||||
5 => {
|
||||
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||
Ok(MultiEraHeader::Babbage(header))
|
||||
Ok(MultiEraHeader::Babbage(Cow::Owned(header)))
|
||||
}
|
||||
_ => {
|
||||
let header = minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||
Ok(MultiEraHeader::AlonzoCompatible(header))
|
||||
Ok(MultiEraHeader::AlonzoCompatible(Cow::Owned(header)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cbor(&self) -> &'b [u8] {
|
||||
match self {
|
||||
MultiEraHeader::EpochBoundary(x) => x.raw_cbor(),
|
||||
MultiEraHeader::AlonzoCompatible(x) => x.raw_cbor(),
|
||||
MultiEraHeader::Babbage(x) => x.raw_cbor(),
|
||||
MultiEraHeader::Byron(x) => x.raw_cbor(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number(&self) -> u64 {
|
||||
match self {
|
||||
MultiEraHeader::EpochBoundary(x) => x
|
||||
|
|
|
|||
|
|
@ -11,18 +11,18 @@ impl OutputRef {
|
|||
Self(hash, index)
|
||||
}
|
||||
|
||||
pub fn tx_id(&self) -> &Hash<32> {
|
||||
pub fn hash(&self) -> &Hash<32> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn tx_index(&self) -> u64 {
|
||||
pub fn index(&self) -> u64 {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for OutputRef {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}#{}", self.tx_id(), self.tx_index())
|
||||
write!(f, "{}#{}", self.hash(), self.index())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,13 +52,33 @@ impl<'b> MultiEraInput<'b> {
|
|||
Self::AlonzoCompatible(Box::new(Cow::Borrowed(input)))
|
||||
}
|
||||
|
||||
pub fn output_ref(&self) -> Option<OutputRef> {
|
||||
pub fn output_ref(&self) -> OutputRef {
|
||||
match self {
|
||||
MultiEraInput::Byron(x) => match x.deref().deref() {
|
||||
byron::TxIn::Variant0(CborWrap((tx, idx))) => Some(OutputRef(*tx, *idx as u64)),
|
||||
byron::TxIn::Other(_, _) => None,
|
||||
byron::TxIn::Variant0(CborWrap((tx, idx))) => OutputRef(*tx, *idx as u64),
|
||||
byron::TxIn::Other(_, _) => unreachable!(),
|
||||
},
|
||||
MultiEraInput::AlonzoCompatible(x) => Some(OutputRef(x.transaction_id, x.index)),
|
||||
MultiEraInput::AlonzoCompatible(x) => OutputRef(x.transaction_id, x.index),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash(&self) -> &Hash<32> {
|
||||
match self {
|
||||
MultiEraInput::Byron(x) => match x.deref().deref() {
|
||||
byron::TxIn::Variant0(CborWrap((x, _))) => x,
|
||||
byron::TxIn::Other(_, _) => unreachable!(),
|
||||
},
|
||||
MultiEraInput::AlonzoCompatible(x) => &x.transaction_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(&self) -> u64 {
|
||||
match self {
|
||||
MultiEraInput::Byron(x) => match x.deref().deref() {
|
||||
byron::TxIn::Variant0(CborWrap((_, x))) => *x as u64,
|
||||
byron::TxIn::Other(_, _) => unreachable!(),
|
||||
},
|
||||
MultiEraInput::AlonzoCompatible(x) => x.index,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,10 +130,9 @@ mod tests {
|
|||
let block = MultiEraBlock::decode(&cbor).expect("invalid cbor");
|
||||
for tx in block.txs() {
|
||||
for input in tx.inputs() {
|
||||
if let Some(out) = input.output_ref() {
|
||||
let right = expected.remove(0);
|
||||
assert_eq!(out.to_string(), right);
|
||||
}
|
||||
let ref_ = input.output_ref();
|
||||
let right = expected.remove(0);
|
||||
assert_eq!(ref_.to_string(), right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -130,10 +149,10 @@ mod tests {
|
|||
let sample = OutputRef::from_str(vector).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
sample.tx_id().to_string(),
|
||||
sample.hash().to_string(),
|
||||
"da832fb5ef57df5b91817e9a7448d26e92552afb34f8ee5adb491b24bbe990d5"
|
||||
);
|
||||
assert_eq!(sample.tx_index(), 14);
|
||||
assert_eq!(sample.index(), 14);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ pub mod era;
|
|||
pub mod header;
|
||||
pub mod input;
|
||||
pub mod meta;
|
||||
pub mod mint;
|
||||
pub mod output;
|
||||
pub mod probe;
|
||||
mod support;
|
||||
pub mod tx;
|
||||
pub mod withdrawals;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[non_exhaustive]
|
||||
|
|
@ -45,16 +47,16 @@ pub enum Feature {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum MultiEraHeader<'b> {
|
||||
EpochBoundary(KeepRaw<'b, byron::EbbHead>),
|
||||
AlonzoCompatible(KeepRaw<'b, alonzo::Header>),
|
||||
Babbage(KeepRaw<'b, babbage::Header>),
|
||||
Byron(KeepRaw<'b, byron::BlockHead>),
|
||||
EpochBoundary(Cow<'b, KeepRaw<'b, byron::EbbHead>>),
|
||||
AlonzoCompatible(Cow<'b, KeepRaw<'b, alonzo::Header>>),
|
||||
Babbage(Cow<'b, KeepRaw<'b, babbage::Header>>),
|
||||
Byron(Cow<'b, KeepRaw<'b, byron::BlockHead>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum MultiEraBlock<'b> {
|
||||
EpochBoundary(Box<Cow<'b, byron::EbBlock>>),
|
||||
EpochBoundary(Box<Cow<'b, byron::MintedEbBlock<'b>>>),
|
||||
AlonzoCompatible(Box<Cow<'b, alonzo::MintedBlock<'b>>>, Era),
|
||||
Babbage(Box<Cow<'b, babbage::MintedBlock<'b>>>),
|
||||
Byron(Box<Cow<'b, byron::MintedBlock<'b>>>),
|
||||
|
|
@ -83,12 +85,36 @@ pub enum MultiEraInput<'b> {
|
|||
AlonzoCompatible(Box<Cow<'b, alonzo::TransactionInput>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum MultiEraCert<'b> {
|
||||
NotApplicable,
|
||||
AlonzoCompatible(Box<Cow<'b, alonzo::Certificate>>),
|
||||
}
|
||||
|
||||
pub struct MultiEraMeta<'b>(Cow<'b, alonzo::Metadata>);
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum MultiEraMeta<'b> {
|
||||
NotApplicable,
|
||||
Empty,
|
||||
AlonzoCompatible(Cow<'b, alonzo::Metadata>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum MultiEraMint<'b> {
|
||||
NotApplicable,
|
||||
Empty,
|
||||
AlonzoCompatible(Cow<'b, alonzo::Mint>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum MultiEraWithdrawals<'b> {
|
||||
NotApplicable,
|
||||
Empty,
|
||||
AlonzoCompatible(Cow<'b, alonzo::Withdrawals>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OutputRef(Hash<32>, u64);
|
||||
|
|
|
|||
|
|
@ -2,14 +2,44 @@ use pallas_primitives::alonzo;
|
|||
|
||||
use crate::MultiEraMeta;
|
||||
|
||||
impl Default for MultiEraMeta<'_> {
|
||||
fn default() -> Self {
|
||||
MultiEraMeta::Empty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> MultiEraMeta<'b> {
|
||||
pub fn entries(&self) -> &alonzo::Metadata {
|
||||
&self.0
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::Metadata> {
|
||||
match self {
|
||||
Self::AlonzoCompatible(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
MultiEraMeta::AlonzoCompatible(x) => x.is_empty(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find(&self, label: alonzo::MetadatumLabel) -> Option<&alonzo::Metadatum> {
|
||||
self.entries()
|
||||
self.as_alonzo()?
|
||||
.iter()
|
||||
.find_map(|(key, value)| if key.eq(&label) { Some(value) } else { None })
|
||||
}
|
||||
|
||||
pub fn collect<'a, T>(&'a self) -> T
|
||||
where
|
||||
T: FromIterator<(&'a alonzo::MetadatumLabel, &'a alonzo::Metadatum)>,
|
||||
{
|
||||
match self {
|
||||
MultiEraMeta::NotApplicable => T::from_iter(std::iter::empty()),
|
||||
MultiEraMeta::Empty => T::from_iter(std::iter::empty()),
|
||||
MultiEraMeta::AlonzoCompatible(x) => {
|
||||
let iter = x.iter().map(|(k, v)| (k, v));
|
||||
T::from_iter(iter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
32
pallas-traverse/src/mint.rs
Normal file
32
pallas-traverse/src/mint.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use pallas_primitives::alonzo;
|
||||
|
||||
use crate::MultiEraMint;
|
||||
|
||||
impl Default for MultiEraMint<'_> {
|
||||
fn default() -> Self {
|
||||
MultiEraMint::Empty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> MultiEraMint<'b> {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
MultiEraMint::AlonzoCompatible(x) => x.len(),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
MultiEraMint::AlonzoCompatible(x) => x.is_empty(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::Mint> {
|
||||
match self {
|
||||
Self::AlonzoCompatible(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{borrow::Cow, ops::Deref};
|
||||
|
||||
use pallas_addresses::{Address, ByronAddress, Error as AddressError};
|
||||
use pallas_addresses::{Address, Error as AddressError};
|
||||
use pallas_codec::minicbor;
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
|
||||
|
|
@ -19,17 +19,21 @@ impl<'b> MultiEraOutput<'b> {
|
|||
Self::Babbage(Box::new(Cow::Borrowed(output)))
|
||||
}
|
||||
|
||||
pub fn to_address(&self) -> Result<Address, AddressError> {
|
||||
pub fn address_raw(&self) -> &[u8] {
|
||||
match self {
|
||||
MultiEraOutput::AlonzoCompatible(x) => Address::from_bytes(&x.address),
|
||||
MultiEraOutput::AlonzoCompatible(x) => &x.address,
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(x) => Address::from_bytes(&x.address),
|
||||
babbage::TransactionOutput::PostAlonzo(x) => Address::from_bytes(&x.address),
|
||||
babbage::TransactionOutput::Legacy(x) => &x.address,
|
||||
babbage::TransactionOutput::PostAlonzo(x) => &x.address,
|
||||
},
|
||||
MultiEraOutput::Byron(x) => Ok(ByronAddress::new(x.address.clone()).into()),
|
||||
MultiEraOutput::Byron(x) => x.address.payload.deref(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn address(&self) -> Result<Address, AddressError> {
|
||||
Address::from_bytes(self.address_raw())
|
||||
}
|
||||
|
||||
pub fn ada_amount(&self) -> u64 {
|
||||
match self {
|
||||
MultiEraOutput::Byron(x) => x.amount,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ use pallas_primitives::{
|
|||
};
|
||||
use std::{borrow::Cow, ops::Deref};
|
||||
|
||||
use crate::{Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraOutput, MultiEraTx};
|
||||
use crate::{
|
||||
Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraTx,
|
||||
MultiEraWithdrawals,
|
||||
};
|
||||
|
||||
impl<'b> MultiEraTx<'b> {
|
||||
pub fn from_byron(tx: &'b byron::MintedTxPayload<'b>) -> Self {
|
||||
|
|
@ -151,6 +154,58 @@ impl<'b> MultiEraTx<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mint(&self) -> MultiEraMint {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => x
|
||||
.transaction_body
|
||||
.mint
|
||||
.as_ref()
|
||||
.map(|c| MultiEraMint::AlonzoCompatible(Cow::Borrowed(c)))
|
||||
.unwrap_or_default(),
|
||||
MultiEraTx::Babbage(x) => x
|
||||
.transaction_body
|
||||
.mint
|
||||
.as_ref()
|
||||
.map(|c| MultiEraMint::AlonzoCompatible(Cow::Borrowed(c)))
|
||||
.unwrap_or_default(),
|
||||
MultiEraTx::Byron(_) => MultiEraMint::NotApplicable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collateral(&self) -> Vec<MultiEraInput> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => x
|
||||
.transaction_body
|
||||
.collateral
|
||||
.iter()
|
||||
.flat_map(|x| x.iter())
|
||||
.map(MultiEraInput::from_alonzo_compatible)
|
||||
.collect(),
|
||||
MultiEraTx::Babbage(x) => x
|
||||
.transaction_body
|
||||
.collateral
|
||||
.iter()
|
||||
.flat_map(|x| x.iter())
|
||||
.map(MultiEraInput::from_alonzo_compatible)
|
||||
.collect(),
|
||||
MultiEraTx::Byron(_) => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn withdrawals(&'b self) -> MultiEraWithdrawals<'b> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => match &x.transaction_body.withdrawals {
|
||||
Some(x) => MultiEraWithdrawals::AlonzoCompatible(Cow::Borrowed(x)),
|
||||
None => MultiEraWithdrawals::Empty,
|
||||
},
|
||||
MultiEraTx::Babbage(x) => match &x.transaction_body.withdrawals {
|
||||
Some(x) => MultiEraWithdrawals::AlonzoCompatible(Cow::Borrowed(x)),
|
||||
None => MultiEraWithdrawals::Empty,
|
||||
},
|
||||
MultiEraTx::Byron(_) => MultiEraWithdrawals::NotApplicable,
|
||||
}
|
||||
}
|
||||
|
||||
fn aux_data(&self) -> Option<&KeepRaw<'_, AuxiliaryData>> {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => x.auxiliary_data.as_ref(),
|
||||
|
|
@ -159,15 +214,28 @@ impl<'b> MultiEraTx<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Option<MultiEraMeta> {
|
||||
match self.aux_data()?.deref() {
|
||||
AuxiliaryData::Shelley(x) => MultiEraMeta(Cow::Borrowed(x)).into(),
|
||||
AuxiliaryData::ShelleyMa(x) => {
|
||||
MultiEraMeta(Cow::Borrowed(&x.transaction_metadata)).into()
|
||||
}
|
||||
AuxiliaryData::PostAlonzo(x) => {
|
||||
x.metadata.as_ref().map(|x| MultiEraMeta(Cow::Borrowed(x)))
|
||||
}
|
||||
pub fn metadata(&'b self) -> MultiEraMeta<'b> {
|
||||
match self.aux_data() {
|
||||
Some(x) => match x.deref() {
|
||||
AuxiliaryData::Shelley(x) => MultiEraMeta::AlonzoCompatible(Cow::Borrowed(x)),
|
||||
AuxiliaryData::ShelleyMa(x) => {
|
||||
MultiEraMeta::AlonzoCompatible(Cow::Borrowed(&x.transaction_metadata))
|
||||
}
|
||||
AuxiliaryData::PostAlonzo(x) => x
|
||||
.metadata
|
||||
.as_ref()
|
||||
.map(|x| MultiEraMeta::AlonzoCompatible(Cow::Borrowed(x)))
|
||||
.unwrap_or_default(),
|
||||
},
|
||||
None => MultiEraMeta::Empty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
match self {
|
||||
MultiEraTx::AlonzoCompatible(x, _) => x.success,
|
||||
MultiEraTx::Babbage(x) => x.success,
|
||||
MultiEraTx::Byron(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
33
pallas-traverse/src/withdrawals.rs
Normal file
33
pallas-traverse/src/withdrawals.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use pallas_primitives::alonzo;
|
||||
|
||||
use crate::MultiEraWithdrawals;
|
||||
|
||||
impl<'b> MultiEraWithdrawals<'b> {
|
||||
pub fn as_alonzo(&self) -> Option<&alonzo::Withdrawals> {
|
||||
match self {
|
||||
Self::AlonzoCompatible(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
MultiEraWithdrawals::AlonzoCompatible(x) => x.is_empty(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect<'a, T>(&'a self) -> T
|
||||
where
|
||||
T: FromIterator<(&'a [u8], u64)>,
|
||||
{
|
||||
match self {
|
||||
MultiEraWithdrawals::NotApplicable => T::from_iter(std::iter::empty()),
|
||||
MultiEraWithdrawals::Empty => T::from_iter(std::iter::empty()),
|
||||
MultiEraWithdrawals::AlonzoCompatible(x) => {
|
||||
let iter = x.iter().map(|(k, v)| (k.as_slice(), v.into()));
|
||||
T::from_iter(iter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue