feat: Introduce 'traverse' library (#117)
This commit is contained in:
parent
c9489c3ddf
commit
6913efef78
20 changed files with 377 additions and 106 deletions
|
|
@ -6,6 +6,7 @@ members = [
|
||||||
"pallas-miniprotocols",
|
"pallas-miniprotocols",
|
||||||
"pallas-crypto",
|
"pallas-crypto",
|
||||||
"pallas-primitives",
|
"pallas-primitives",
|
||||||
|
"pallas-traverse",
|
||||||
"pallas",
|
"pallas",
|
||||||
"examples/block-download",
|
"examples/block-download",
|
||||||
"examples/block-decode",
|
"examples/block-decode",
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ As already explained, _Pallas_ aims at being an expanding set of components. The
|
||||||
| Crates | Description |
|
| Crates | Description |
|
||||||
| --------------------------------------- | ----------------------------------------------------------------------- |
|
| --------------------------------------- | ----------------------------------------------------------------------- |
|
||||||
| [pallas-primitives](/pallas-primitives) | Ledger primitives and cbor codec for the different Cardano eras |
|
| [pallas-primitives](/pallas-primitives) | Ledger primitives and cbor codec for the different Cardano eras |
|
||||||
|
| [pallas-traverse](/pallas-traverse) | Utilities to traverse over multi-era block data |
|
||||||
| pallas-ticking | Time passage implementation for consensus algorithm |
|
| pallas-ticking | Time passage implementation for consensus algorithm |
|
||||||
| pallas-applying | Logic for validating and applying new blocks and txs to the chain state |
|
| pallas-applying | Logic for validating and applying new blocks and txs to the chain state |
|
||||||
| pallas-forecasting | Ledger forecasting algorithm to be used by the consensus layer |
|
| pallas-forecasting | Ledger forecasting algorithm to be used by the consensus layer |
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use pallas::ledger::primitives::{alonzo, byron, probing, Era};
|
use pallas::ledger::traverse::MultiEraBlock;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let blocks = vec![
|
let blocks = vec![
|
||||||
|
|
@ -10,23 +10,14 @@ fn main() {
|
||||||
];
|
];
|
||||||
|
|
||||||
for block_str in blocks.iter() {
|
for block_str in blocks.iter() {
|
||||||
let bytes = hex::decode(block_str).expect("invalid hex");
|
let cbor = hex::decode(block_str).expect("invalid hex");
|
||||||
|
|
||||||
match probing::probe_block_cbor_era(&bytes) {
|
let block = MultiEraBlock::decode(&cbor).expect("invalid cbor");
|
||||||
probing::Outcome::Matched(era) => match era {
|
|
||||||
Era::Byron => {
|
println!("{} {}", block.slot(), block.hash());
|
||||||
let (_, block): (u16, byron::MainBlock) =
|
|
||||||
pallas::codec::minicbor::decode(&bytes).expect("invalid cbor");
|
for tx in block.tx_iter() {
|
||||||
println!("{:?}", block)
|
println!("{:?}", tx);
|
||||||
}
|
}
|
||||||
// we use alonzo for everything post-shelly since it's backward compatible
|
|
||||||
Era::Shelley | Era::Allegra | Era::Mary | Era::Alonzo => {
|
|
||||||
let (_, block): (u16, alonzo::Block) =
|
|
||||||
pallas::codec::minicbor::decode(&bytes).expect("invalid cbor");
|
|
||||||
println!("{:?}", block)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => println!("couldn't infer block era"),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that maintains a reference to whether a cbor array was indef or not
|
/// A struct that maintains a reference to whether a cbor array was indef or not
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum MaybeIndefArray<A> {
|
pub enum MaybeIndefArray<A> {
|
||||||
Def(Vec<A>),
|
Def(Vec<A>),
|
||||||
Indef(Vec<A>),
|
Indef(Vec<A>),
|
||||||
|
|
@ -186,7 +186,7 @@ where
|
||||||
/// transform key-value structures into an orderer vec of `properties`, 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
|
/// each entry represents a a cbor-encodable variant of an attribute of the
|
||||||
/// struct.
|
/// struct.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct OrderPreservingProperties<P>(Vec<P>);
|
pub struct OrderPreservingProperties<P>(Vec<P>);
|
||||||
|
|
||||||
impl<P> Deref for OrderPreservingProperties<P> {
|
impl<P> Deref for OrderPreservingProperties<P> {
|
||||||
|
|
@ -229,7 +229,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a struct so that it is encoded/decoded as a cbor bytes
|
/// Wraps a struct so that it is encoded/decoded as a cbor bytes
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CborWrap<T>(pub T);
|
pub struct CborWrap<T>(pub T);
|
||||||
|
|
||||||
impl<'b, C, T> minicbor::Decode<'b, C> for CborWrap<T>
|
impl<'b, C, T> minicbor::Decode<'b, C> for CborWrap<T>
|
||||||
|
|
@ -312,7 +312,7 @@ where
|
||||||
/// An empty map
|
/// An empty map
|
||||||
///
|
///
|
||||||
/// don't ask me why, that's what the CDDL asks for.
|
/// don't ask me why, that's what the CDDL asks for.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EmptyMap;
|
pub struct EmptyMap;
|
||||||
|
|
||||||
impl<'b, C> minicbor::decode::Decode<'b, C> for EmptyMap {
|
impl<'b, C> minicbor::decode::Decode<'b, C> for EmptyMap {
|
||||||
|
|
@ -518,7 +518,7 @@ impl From<&AnyUInt> for u64 {
|
||||||
/// let confirm: (u16, u16) = minicbor::decode(keeper.raw_cbor()).unwrap();
|
/// let confirm: (u16, u16) = minicbor::decode(keeper.raw_cbor()).unwrap();
|
||||||
/// assert_eq!(confirm, (456u16, 789u16));
|
/// assert_eq!(confirm, (456u16, 789u16));
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, PartialEq, PartialOrd)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||||
pub struct KeepRaw<'b, T> {
|
pub struct KeepRaw<'b, T> {
|
||||||
raw: &'b [u8],
|
raw: &'b [u8],
|
||||||
inner: T,
|
inner: T,
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ pub struct Header {
|
||||||
pub body_signature: ByteVec,
|
pub body_signature: ByteVec,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct TransactionInput {
|
pub struct TransactionInput {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub transaction_id: Hash<32>,
|
pub transaction_id: Hash<32>,
|
||||||
|
|
@ -85,7 +85,7 @@ pub struct TransactionInput {
|
||||||
|
|
||||||
// $nonce /= [ 0 // 1, bytes .size 32 ]
|
// $nonce /= [ 0 // 1, bytes .size 32 ]
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(index_only)]
|
#[cbor(index_only)]
|
||||||
pub enum NonceVariant {
|
pub enum NonceVariant {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -95,7 +95,7 @@ pub enum NonceVariant {
|
||||||
Nonce,
|
Nonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct Nonce {
|
pub struct Nonce {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub variant: NonceVariant,
|
pub variant: NonceVariant,
|
||||||
|
|
@ -162,7 +162,7 @@ impl<C> minicbor::encode::Encode<C> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct TransactionOutput {
|
pub struct TransactionOutput {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub address: ByteVec,
|
pub address: ByteVec,
|
||||||
|
|
@ -187,7 +187,7 @@ pub type VrfKeyhash = Hash<32>;
|
||||||
; otherwise the funds are given to the other accounting pot.
|
; otherwise the funds are given to the other accounting pot.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||||
pub enum InstantaneousRewardSource {
|
pub enum InstantaneousRewardSource {
|
||||||
Reserves,
|
Reserves,
|
||||||
Treasury,
|
Treasury,
|
||||||
|
|
@ -225,7 +225,7 @@ impl<C> minicbor::encode::Encode<C> for InstantaneousRewardSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||||
pub enum InstantaneousRewardTarget {
|
pub enum InstantaneousRewardTarget {
|
||||||
StakeCredentials(KeyValuePairs<StakeCredential, i64>),
|
StakeCredentials(KeyValuePairs<StakeCredential, i64>),
|
||||||
OtherAccountingPot(Coin),
|
OtherAccountingPot(Coin),
|
||||||
|
|
@ -267,7 +267,7 @@ impl<C> minicbor::encode::Encode<C> for InstantaneousRewardTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq, PartialOrd)]
|
#[derive(Encode, Decode, Debug, PartialEq, PartialOrd, Clone)]
|
||||||
#[cbor]
|
#[cbor]
|
||||||
pub struct MoveInstantaneousReward {
|
pub struct MoveInstantaneousReward {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -284,7 +284,7 @@ pub type IPv4 = ByteVec;
|
||||||
pub type IPv6 = ByteVec;
|
pub type IPv6 = ByteVec;
|
||||||
pub type DnsName = String;
|
pub type DnsName = String;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Relay {
|
pub enum Relay {
|
||||||
SingleHostAddr(Option<Port>, Option<IPv4>, Option<IPv6>),
|
SingleHostAddr(Option<Port>, Option<IPv4>, Option<IPv6>),
|
||||||
SingleHostName(Option<Port>, DnsName),
|
SingleHostName(Option<Port>, DnsName),
|
||||||
|
|
@ -351,7 +351,7 @@ impl<C> minicbor::encode::Encode<C> for Relay {
|
||||||
|
|
||||||
pub type PoolMetadataHash = Hash<32>;
|
pub type PoolMetadataHash = Hash<32>;
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct PoolMetadata {
|
pub struct PoolMetadata {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub url: String,
|
pub url: String,
|
||||||
|
|
@ -363,7 +363,7 @@ pub struct PoolMetadata {
|
||||||
pub type AddrKeyhash = Hash<28>;
|
pub type AddrKeyhash = Hash<28>;
|
||||||
pub type Scripthash = Hash<28>;
|
pub type Scripthash = Hash<28>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct RationalNumber {
|
pub struct RationalNumber {
|
||||||
pub numerator: i64,
|
pub numerator: i64,
|
||||||
pub denominator: u64,
|
pub denominator: u64,
|
||||||
|
|
@ -401,7 +401,7 @@ pub type UnitInterval = RationalNumber;
|
||||||
|
|
||||||
pub type PositiveInterval = RationalNumber;
|
pub type PositiveInterval = RationalNumber;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
|
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
|
||||||
pub enum StakeCredential {
|
pub enum StakeCredential {
|
||||||
AddrKeyhash(AddrKeyhash),
|
AddrKeyhash(AddrKeyhash),
|
||||||
Scripthash(Scripthash),
|
Scripthash(Scripthash),
|
||||||
|
|
@ -447,7 +447,7 @@ impl<C> minicbor::encode::Encode<C> for StakeCredential {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Certificate {
|
pub enum Certificate {
|
||||||
StakeRegistration(StakeCredential),
|
StakeRegistration(StakeCredential),
|
||||||
StakeDeregistration(StakeCredential),
|
StakeDeregistration(StakeCredential),
|
||||||
|
|
@ -615,7 +615,7 @@ impl<C> minicbor::encode::Encode<C> for Certificate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
#[cbor(index_only)]
|
#[cbor(index_only)]
|
||||||
pub enum NetworkId {
|
pub enum NetworkId {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -624,7 +624,7 @@ pub enum NetworkId {
|
||||||
Two,
|
Two,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(index_only)]
|
#[cbor(index_only)]
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -637,7 +637,7 @@ pub type CostMdls = KeyValuePairs<Language, CostModel>;
|
||||||
|
|
||||||
pub type ProtocolVersion = (u32, u32);
|
pub type ProtocolVersion = (u32, u32);
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(map)]
|
#[cbor(map)]
|
||||||
pub struct ProtocolParamUpdate {
|
pub struct ProtocolParamUpdate {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -690,7 +690,7 @@ pub struct ProtocolParamUpdate {
|
||||||
pub max_collateral_inputs: Option<u32>,
|
pub max_collateral_inputs: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct Update {
|
pub struct Update {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub proposed_protocol_parameter_updates: KeyValuePairs<Genesishash, ProtocolParamUpdate>,
|
pub proposed_protocol_parameter_updates: KeyValuePairs<Genesishash, ProtocolParamUpdate>,
|
||||||
|
|
@ -699,7 +699,7 @@ pub struct Update {
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum TransactionBodyComponent {
|
pub enum TransactionBodyComponent {
|
||||||
Inputs(MaybeIndefArray<TransactionInput>),
|
Inputs(MaybeIndefArray<TransactionInput>),
|
||||||
Outputs(MaybeIndefArray<TransactionOutput>),
|
Outputs(MaybeIndefArray<TransactionOutput>),
|
||||||
|
|
@ -814,7 +814,7 @@ impl<C> minicbor::encode::Encode<C> for TransactionBodyComponent {
|
||||||
|
|
||||||
// Can't derive encode for TransactionBody because it seems to require a very
|
// Can't derive encode for TransactionBody because it seems to require a very
|
||||||
// particular order for each key in the map
|
// particular order for each key in the map
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct TransactionBody(Vec<TransactionBodyComponent>);
|
pub struct TransactionBody(Vec<TransactionBodyComponent>);
|
||||||
|
|
||||||
impl Deref for TransactionBody {
|
impl Deref for TransactionBody {
|
||||||
|
|
@ -850,7 +850,7 @@ impl<C> minicbor::encode::Encode<C> for TransactionBody {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct VKeyWitness {
|
pub struct VKeyWitness {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub vkey: ByteVec,
|
pub vkey: ByteVec,
|
||||||
|
|
@ -859,7 +859,7 @@ pub struct VKeyWitness {
|
||||||
pub signature: ByteVec,
|
pub signature: ByteVec,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum NativeScript {
|
pub enum NativeScript {
|
||||||
ScriptPubkey(AddrKeyhash),
|
ScriptPubkey(AddrKeyhash),
|
||||||
ScriptAll(MaybeIndefArray<NativeScript>),
|
ScriptAll(MaybeIndefArray<NativeScript>),
|
||||||
|
|
@ -931,7 +931,7 @@ impl<C> minicbor::encode::Encode<C> for NativeScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(transparent)]
|
#[cbor(transparent)]
|
||||||
pub struct PlutusScript(#[n(0)] pub ByteVec);
|
pub struct PlutusScript(#[n(0)] pub ByteVec);
|
||||||
|
|
||||||
|
|
@ -947,7 +947,7 @@ big_uint = #6.2(bounded_bytes) ; New
|
||||||
big_nint = #6.3(bounded_bytes) ; New
|
big_nint = #6.3(bounded_bytes) ; New
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum BigInt {
|
pub enum BigInt {
|
||||||
Int(Int),
|
Int(Int),
|
||||||
BigUInt(ByteVec),
|
BigUInt(ByteVec),
|
||||||
|
|
@ -1009,7 +1009,7 @@ impl<C> minicbor::encode::Encode<C> for BigInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum PlutusData {
|
pub enum PlutusData {
|
||||||
Constr(Constr<PlutusData>),
|
Constr(Constr<PlutusData>),
|
||||||
Map(KeyValuePairs<PlutusData, PlutusData>),
|
Map(KeyValuePairs<PlutusData, PlutusData>),
|
||||||
|
|
@ -1090,7 +1090,7 @@ impl<C> minicbor::encode::Encode<C> for PlutusData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct Constr<A> {
|
pub struct Constr<A> {
|
||||||
pub tag: u64,
|
pub tag: u64,
|
||||||
pub any_constructor: Option<u64>,
|
pub any_constructor: Option<u64>,
|
||||||
|
|
@ -1159,7 +1159,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct ExUnits {
|
pub struct ExUnits {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub mem: u32,
|
pub mem: u32,
|
||||||
|
|
@ -1167,7 +1167,7 @@ pub struct ExUnits {
|
||||||
pub steps: u64,
|
pub steps: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct ExUnitPrices {
|
pub struct ExUnitPrices {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
mem_price: PositiveInterval,
|
mem_price: PositiveInterval,
|
||||||
|
|
@ -1176,7 +1176,7 @@ pub struct ExUnitPrices {
|
||||||
step_price: PositiveInterval,
|
step_price: PositiveInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(index_only)]
|
#[cbor(index_only)]
|
||||||
pub enum RedeemerTag {
|
pub enum RedeemerTag {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -1189,7 +1189,7 @@ pub enum RedeemerTag {
|
||||||
Reward,
|
Reward,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct Redeemer {
|
pub struct Redeemer {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub tag: RedeemerTag,
|
pub tag: RedeemerTag,
|
||||||
|
|
@ -1211,7 +1211,7 @@ pub struct Redeemer {
|
||||||
, attributes : bytes
|
, attributes : bytes
|
||||||
] */
|
] */
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct BootstrapWitness {
|
pub struct BootstrapWitness {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub public_key: ByteVec,
|
pub public_key: ByteVec,
|
||||||
|
|
@ -1226,7 +1226,7 @@ pub struct BootstrapWitness {
|
||||||
pub attributes: ByteVec,
|
pub attributes: ByteVec,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(map)]
|
#[cbor(map)]
|
||||||
pub struct TransactionWitnessSet {
|
pub struct TransactionWitnessSet {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -1248,7 +1248,7 @@ pub struct TransactionWitnessSet {
|
||||||
pub redeemer: Option<MaybeIndefArray<Redeemer>>,
|
pub redeemer: Option<MaybeIndefArray<Redeemer>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(map)]
|
#[cbor(map)]
|
||||||
pub struct AlonzoAuxiliaryData {
|
pub struct AlonzoAuxiliaryData {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -1259,7 +1259,7 @@ pub struct AlonzoAuxiliaryData {
|
||||||
pub plutus_scripts: Option<MaybeIndefArray<PlutusScript>>,
|
pub plutus_scripts: Option<MaybeIndefArray<PlutusScript>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum Metadatum {
|
pub enum Metadatum {
|
||||||
Int(Int),
|
Int(Int),
|
||||||
Bytes(ByteVec),
|
Bytes(ByteVec),
|
||||||
|
|
@ -1350,7 +1350,7 @@ pub type MetadatumLabel = AnyUInt;
|
||||||
|
|
||||||
pub type Metadata = KeyValuePairs<MetadatumLabel, Metadatum>;
|
pub type Metadata = KeyValuePairs<MetadatumLabel, Metadatum>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum AuxiliaryData {
|
pub enum AuxiliaryData {
|
||||||
Shelley(Metadata),
|
Shelley(Metadata),
|
||||||
ShelleyMa {
|
ShelleyMa {
|
||||||
|
|
@ -1417,7 +1417,7 @@ impl<C> minicbor::Encode<C> for AuxiliaryData {
|
||||||
|
|
||||||
pub type TransactionIndex = u32;
|
pub type TransactionIndex = u32;
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, PartialEq)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub header: Header,
|
pub header: Header,
|
||||||
|
|
@ -1459,18 +1459,33 @@ pub struct MintedBlock<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
pub struct Transaction {
|
pub struct Tx {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
transaction_body: TransactionBody,
|
pub transaction_body: TransactionBody,
|
||||||
|
|
||||||
#[n(1)]
|
#[n(1)]
|
||||||
transaction_witness_set: TransactionWitnessSet,
|
pub transaction_witness_set: TransactionWitnessSet,
|
||||||
|
|
||||||
#[n(2)]
|
#[n(2)]
|
||||||
success: bool,
|
pub success: bool,
|
||||||
|
|
||||||
#[n(3)]
|
#[n(3)]
|
||||||
auxiliary_data: Option<AuxiliaryData>,
|
pub auxiliary_data: Option<AuxiliaryData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Encode, Decode, Debug)]
|
||||||
|
pub struct MintedTx<'b> {
|
||||||
|
#[b(0)]
|
||||||
|
pub transaction_body: KeepRaw<'b, TransactionBody>,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub transaction_witness_set: TransactionWitnessSet,
|
||||||
|
|
||||||
|
#[n(2)]
|
||||||
|
pub success: bool,
|
||||||
|
|
||||||
|
#[n(3)]
|
||||||
|
pub auxiliary_data: Option<KeepRaw<'b, AuxiliaryData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ impl Address {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::byron::MintedMainBlock;
|
use crate::byron::MintedBlock;
|
||||||
|
|
||||||
type BlockWrapper<'b> = (u16, MintedMainBlock<'b>);
|
type BlockWrapper<'b> = (u16, MintedBlock<'b>);
|
||||||
|
|
||||||
const KNOWN_ADDRESSES: &[&str] = &[
|
const KNOWN_ADDRESSES: &[&str] = &[
|
||||||
"DdzFFzCqrht8QHTQXbWy2qoyPaqTN8BjyfKygGmpy9dtot1tvkBfCaVTnR22XCaaDVn3M1U6aiMShoCLzw6VWSwzQKhhJrM3YjYp3wyy",
|
"DdzFFzCqrht8QHTQXbWy2qoyPaqTN8BjyfKygGmpy9dtot1tvkBfCaVTnR22XCaaDVn3M1U6aiMShoCLzw6VWSwzQKhhJrM3YjYp3wyy",
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ impl ToHash<32> for KeepRaw<'_, Tx> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use pallas_codec::minicbor;
|
use pallas_codec::minicbor;
|
||||||
|
|
||||||
use crate::{byron::MintedMainBlock, ToHash};
|
use crate::{byron::MintedBlock, ToHash};
|
||||||
|
|
||||||
type BlockWrapper<'b> = (u16, MintedMainBlock<'b>);
|
type BlockWrapper<'b> = (u16, MintedBlock<'b>);
|
||||||
|
|
||||||
const KNOWN_HASH: &'static str =
|
const KNOWN_HASH: &'static str =
|
||||||
"5c196e7394ace0449ba5a51c919369699b13896e97432894b4f0354dce8670b6";
|
"5c196e7394ace0449ba5a51c919369699b13896e97432894b4f0354dce8670b6";
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ impl TxPayload {
|
||||||
mod tests {
|
mod tests {
|
||||||
use pallas_codec::minicbor;
|
use pallas_codec::minicbor;
|
||||||
|
|
||||||
use crate::{byron::MainBlock, ToHash};
|
use crate::{byron::Block, ToHash};
|
||||||
|
|
||||||
type BlockWrapper = (u16, MainBlock);
|
type BlockWrapper = (u16, Block);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn known_fee_matches() {
|
fn known_fee_matches() {
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ pub type Attributes = EmptyMap;
|
||||||
|
|
||||||
// Addresses
|
// Addresses
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum AddrDistr {
|
pub enum AddrDistr {
|
||||||
Variant0(StakeholderId),
|
Variant0(StakeholderId),
|
||||||
Variant1,
|
Variant1,
|
||||||
|
|
@ -96,7 +96,7 @@ impl minicbor::Encode<()> for AddrDistr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum AddrType {
|
pub enum AddrType {
|
||||||
PubKey,
|
PubKey,
|
||||||
Script,
|
Script,
|
||||||
|
|
@ -137,7 +137,7 @@ impl<C> minicbor::Encode<C> for AddrType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum AddrAttrProperty {
|
pub enum AddrAttrProperty {
|
||||||
AddrDistr(AddrDistr),
|
AddrDistr(AddrDistr),
|
||||||
Bytes(ByteVec),
|
Bytes(ByteVec),
|
||||||
|
|
@ -187,7 +187,7 @@ impl<C> minicbor::Encode<C> for AddrAttrProperty {
|
||||||
|
|
||||||
pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;
|
pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;
|
||||||
|
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Encode, Decode, Clone)]
|
||||||
pub struct AddressPayload {
|
pub struct AddressPayload {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub root: AddressId,
|
pub root: AddressId,
|
||||||
|
|
@ -200,7 +200,7 @@ pub struct AddressPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
// address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ]
|
// address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ]
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Encode, Decode, Clone)]
|
||||||
pub struct Address {
|
pub struct Address {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub payload: CborWrap<AddressPayload>,
|
pub payload: CborWrap<AddressPayload>,
|
||||||
|
|
@ -212,7 +212,7 @@ pub struct Address {
|
||||||
// Transactions
|
// Transactions
|
||||||
|
|
||||||
// txout = [address, u64]
|
// txout = [address, u64]
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Encode, Decode, Clone)]
|
||||||
pub struct TxOut {
|
pub struct TxOut {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub address: Address,
|
pub address: Address,
|
||||||
|
|
@ -221,7 +221,7 @@ pub struct TxOut {
|
||||||
pub amount: u64,
|
pub amount: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TxIn {
|
pub enum TxIn {
|
||||||
// [0, #6.24(bytes .cbor ([txid, u32]))]
|
// [0, #6.24(bytes .cbor ([txid, u32]))]
|
||||||
Variant0(CborWrap<(TxId, u32)>),
|
Variant0(CborWrap<(TxId, u32)>),
|
||||||
|
|
@ -269,7 +269,7 @@ impl<C> minicbor::Encode<C> for TxIn {
|
||||||
}
|
}
|
||||||
|
|
||||||
// tx = [[+ txin], [+ txout], attributes]
|
// tx = [[+ txin], [+ txout], attributes]
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Encode, Decode, Clone)]
|
||||||
pub struct Tx {
|
pub struct Tx {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub inputs: MaybeIndefArray<TxIn>,
|
pub inputs: MaybeIndefArray<TxIn>,
|
||||||
|
|
@ -287,7 +287,7 @@ pub type TxProof = (u32, ByronHash, ByronHash);
|
||||||
pub type ValidatorScript = (u16, ByteVec);
|
pub type ValidatorScript = (u16, ByteVec);
|
||||||
pub type RedeemerScript = (u16, ByteVec);
|
pub type RedeemerScript = (u16, ByteVec);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Twit {
|
pub enum Twit {
|
||||||
// [0, #6.24(bytes .cbor ([pubkey, signature]))]
|
// [0, #6.24(bytes .cbor ([pubkey, signature]))]
|
||||||
PkWitness(CborWrap<(PubKey, Signature)>),
|
PkWitness(CborWrap<(PubKey, Signature)>),
|
||||||
|
|
@ -841,7 +841,6 @@ pub struct BlockHead {
|
||||||
pub extra_data: BlockHeadEx,
|
pub extra_data: BlockHeadEx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// [tx, [* twit]]
|
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Encode, Decode)]
|
||||||
pub struct TxPayload {
|
pub struct TxPayload {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -851,6 +850,15 @@ pub struct TxPayload {
|
||||||
pub witness: MaybeIndefArray<Twit>,
|
pub witness: MaybeIndefArray<Twit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Encode, Decode, Clone)]
|
||||||
|
pub struct MintedTxPayload<'b> {
|
||||||
|
#[b(0)]
|
||||||
|
pub transaction: KeepRaw<'b, Tx>,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub witness: MaybeIndefArray<Twit>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
pub struct BlockBody {
|
pub struct BlockBody {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
|
|
@ -866,6 +874,21 @@ pub struct BlockBody {
|
||||||
pub upd_payload: Up,
|
pub upd_payload: Up,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Encode, Decode, Debug)]
|
||||||
|
pub struct MintedBlockBody<'b> {
|
||||||
|
#[b(0)]
|
||||||
|
pub tx_payload: MaybeIndefArray<MintedTxPayload<'b>>,
|
||||||
|
|
||||||
|
#[b(1)]
|
||||||
|
pub ssc_payload: Ssc,
|
||||||
|
|
||||||
|
#[b(2)]
|
||||||
|
pub dlg_payload: MaybeIndefArray<Dlg>,
|
||||||
|
|
||||||
|
#[b(3)]
|
||||||
|
pub upd_payload: Up,
|
||||||
|
}
|
||||||
|
|
||||||
// Epoch Boundary Blocks
|
// Epoch Boundary Blocks
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
|
|
@ -896,7 +919,7 @@ pub struct EbbHead {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
pub struct MainBlock {
|
pub struct Block {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub header: BlockHead,
|
pub header: BlockHead,
|
||||||
|
|
||||||
|
|
@ -908,12 +931,12 @@ pub struct MainBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
pub struct MintedMainBlock<'b> {
|
pub struct MintedBlock<'b> {
|
||||||
#[b(0)]
|
#[b(0)]
|
||||||
pub header: KeepRaw<'b, BlockHead>,
|
pub header: KeepRaw<'b, BlockHead>,
|
||||||
|
|
||||||
#[n(1)]
|
#[b(1)]
|
||||||
pub body: BlockBody,
|
pub body: MintedBlockBody<'b>,
|
||||||
|
|
||||||
#[n(2)]
|
#[n(2)]
|
||||||
pub extra: MaybeIndefArray<Attributes>,
|
pub extra: MaybeIndefArray<Attributes>,
|
||||||
|
|
@ -933,7 +956,7 @@ pub struct EbBlock {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{BlockHead, EbBlock, MintedMainBlock};
|
use super::{BlockHead, EbBlock, MintedBlock};
|
||||||
use pallas_codec::minicbor::{self, to_vec};
|
use pallas_codec::minicbor::{self, to_vec};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -958,7 +981,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn main_block_isomorphic_decoding_encoding() {
|
fn main_block_isomorphic_decoding_encoding() {
|
||||||
type BlockWrapper<'b> = (u16, MintedMainBlock<'b>);
|
type BlockWrapper<'b> = (u16, MintedBlock<'b>);
|
||||||
|
|
||||||
let test_blocks = vec![
|
let test_blocks = vec![
|
||||||
//include_str!("../../../test_data/genesis.block"),
|
//include_str!("../../../test_data/genesis.block"),
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ impl EbbHead {
|
||||||
mod tests {
|
mod tests {
|
||||||
use pallas_codec::minicbor;
|
use pallas_codec::minicbor;
|
||||||
|
|
||||||
use crate::byron::MainBlock;
|
use crate::byron::Block;
|
||||||
|
|
||||||
type BlockWrapper = (u16, MainBlock);
|
type BlockWrapper = (u16, Block);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn knwon_slot_matches() {
|
fn knwon_slot_matches() {
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub enum Era {
|
|
||||||
Byron,
|
|
||||||
Shelley,
|
|
||||||
Allegra, // time-locks
|
|
||||||
Mary, // multi-assets
|
|
||||||
Alonzo, // smart-contracts
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
pub trait ToCanonicalJson {
|
pub trait ToCanonicalJson {
|
||||||
fn to_json(&self) -> serde_json::Value;
|
fn to_json(&self) -> serde_json::Value;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,5 @@ mod framework;
|
||||||
|
|
||||||
pub mod alonzo;
|
pub mod alonzo;
|
||||||
pub mod byron;
|
pub mod byron;
|
||||||
pub mod probing;
|
|
||||||
|
|
||||||
pub use framework::*;
|
pub use framework::*;
|
||||||
|
|
|
||||||
20
pallas-traverse/Cargo.toml
Normal file
20
pallas-traverse/Cargo.toml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "pallas-traverse"
|
||||||
|
description = "Utilities to traverse over multi-era block data"
|
||||||
|
version = "0.11.0-alpha.0"
|
||||||
|
edition = "2021"
|
||||||
|
repository = "https://github.com/txpipe/pallas"
|
||||||
|
homepage = "https://github.com/txpipe/pallas"
|
||||||
|
documentation = "https://docs.rs/pallas-traverse"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = [
|
||||||
|
"Santiago Carmuega <santiago@carmuega.me>",
|
||||||
|
]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
pallas-primitives = { version = "0.11.0-alpha.0", path = "../pallas-primitives" }
|
||||||
|
pallas-crypto = { version = "0.11.0-alpha.0", path = "../pallas-crypto" }
|
||||||
|
pallas-codec = { version = "0.11.0-alpha.0", path = "../pallas-codec" }
|
||||||
|
hex = "0.4.3"
|
||||||
|
thiserror = "1.0.31"
|
||||||
63
pallas-traverse/src/block.rs
Normal file
63
pallas-traverse/src/block.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
use pallas_codec::minicbor;
|
||||||
|
use pallas_crypto::hash::Hash;
|
||||||
|
use pallas_primitives::{alonzo, byron, ToHash};
|
||||||
|
|
||||||
|
use crate::{probe, Era, Error, MultiEraBlock};
|
||||||
|
|
||||||
|
type BlockWrapper<T> = (u16, T);
|
||||||
|
|
||||||
|
impl<'b> MultiEraBlock<'b> {
|
||||||
|
pub fn from_epoch_boundary(block: byron::EbBlock) -> Self {
|
||||||
|
Self::EpochBoundary(Box::new(block))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_byron(block: byron::MintedBlock<'b>) -> Self {
|
||||||
|
Self::Byron(Box::new(block))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_alonzo_compatible(block: alonzo::MintedBlock<'b>) -> Self {
|
||||||
|
Self::AlonzoCompatible(Box::new(block))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode(cbor: &'b [u8]) -> Result<MultiEraBlock<'b>, Error> {
|
||||||
|
match probe::block_era(cbor) {
|
||||||
|
probe::Outcome::EpochBoundary => {
|
||||||
|
let (_, block): BlockWrapper<byron::EbBlock> =
|
||||||
|
minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||||
|
|
||||||
|
Ok(MultiEraBlock::from_epoch_boundary(block))
|
||||||
|
}
|
||||||
|
probe::Outcome::Matched(era) => match era {
|
||||||
|
Era::Byron => {
|
||||||
|
let (_, block): BlockWrapper<byron::MintedBlock> =
|
||||||
|
minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||||
|
|
||||||
|
Ok(Self::from_byron(block))
|
||||||
|
}
|
||||||
|
Era::Shelley | Era::Allegra | Era::Mary | Era::Alonzo => {
|
||||||
|
let (_, block): BlockWrapper<alonzo::MintedBlock> =
|
||||||
|
minicbor::decode(cbor).map_err(Error::invalid_cbor)?;
|
||||||
|
|
||||||
|
Ok(Self::from_alonzo_compatible(block))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
probe::Outcome::Inconclusive => Err(Error::unknown_cbor(cbor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash(&self) -> Hash<32> {
|
||||||
|
match self {
|
||||||
|
MultiEraBlock::EpochBoundary(x) => x.header.to_hash(),
|
||||||
|
MultiEraBlock::AlonzoCompatible(x) => x.header.to_hash(),
|
||||||
|
MultiEraBlock::Byron(x) => x.header.to_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::Byron(x) => x.header.consensus_data.0.to_abs_slot(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
pallas-traverse/src/iter.rs
Normal file
96
pallas-traverse/src/iter.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
//! Iterate over block data
|
||||||
|
|
||||||
|
use pallas_primitives::{alonzo, byron};
|
||||||
|
|
||||||
|
use crate::{MultiEraBlock, MultiEraTx};
|
||||||
|
|
||||||
|
fn clone_alonzo_tx_at<'b>(
|
||||||
|
block: &'b alonzo::MintedBlock,
|
||||||
|
index: usize,
|
||||||
|
) -> Option<alonzo::MintedTx<'b>> {
|
||||||
|
let transaction_body = block.transaction_bodies.get(index).cloned()?;
|
||||||
|
let transaction_witness_set = block.transaction_witness_sets.get(index).cloned()?;
|
||||||
|
let success = block
|
||||||
|
.invalid_transactions
|
||||||
|
.as_ref()?
|
||||||
|
.contains(&(index as u32));
|
||||||
|
|
||||||
|
let auxiliary_data = block
|
||||||
|
.auxiliary_data_set
|
||||||
|
.iter()
|
||||||
|
.find_map(|(idx, val)| {
|
||||||
|
if idx.eq(&(index as u32)) {
|
||||||
|
Some(val)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.cloned();
|
||||||
|
|
||||||
|
Some(alonzo::MintedTx {
|
||||||
|
transaction_body,
|
||||||
|
transaction_witness_set,
|
||||||
|
success,
|
||||||
|
auxiliary_data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_byron_tx_at<'b>(
|
||||||
|
block: &'b byron::MintedBlock,
|
||||||
|
index: usize,
|
||||||
|
) -> Option<byron::MintedTxPayload<'b>> {
|
||||||
|
block.body.tx_payload.get(index).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TxIter<'b> {
|
||||||
|
block: &'b MultiEraBlock<'b>,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b> Iterator for TxIter<'b> {
|
||||||
|
type Item = MultiEraTx<'b>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let tx = match self.block {
|
||||||
|
MultiEraBlock::EpochBoundary(_) => None,
|
||||||
|
MultiEraBlock::AlonzoCompatible(x) => {
|
||||||
|
clone_alonzo_tx_at(x, self.index).map(MultiEraTx::from_alonzo_compatible)
|
||||||
|
}
|
||||||
|
MultiEraBlock::Byron(x) => clone_byron_tx_at(x, self.index).map(MultiEraTx::from_byron),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
self.index += 1;
|
||||||
|
Some(tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b> MultiEraBlock<'b> {
|
||||||
|
pub fn tx_iter(&'b self) -> TxIter<'b> {
|
||||||
|
TxIter {
|
||||||
|
index: 0,
|
||||||
|
block: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_iteration() {
|
||||||
|
let blocks = vec![
|
||||||
|
(include_str!("../../test_data/byron2.block"), 2usize),
|
||||||
|
(include_str!("../../test_data/shelley1.block"), 0),
|
||||||
|
(include_str!("../../test_data/mary1.block"), 0),
|
||||||
|
(include_str!("../../test_data/allegra1.block"), 0),
|
||||||
|
(include_str!("../../test_data/alonzo1.block"), 5),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (block_str, tx_count) in blocks.into_iter() {
|
||||||
|
let cbor = hex::decode(block_str).expect("invalid hex");
|
||||||
|
let block = MultiEraBlock::decode(&cbor).expect("invalid cbor");
|
||||||
|
assert_eq!(block.tx_iter().count(), tx_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
pallas-traverse/src/lib.rs
Normal file
54
pallas-traverse/src/lib.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
//! Utilities to traverse over multi-era block data
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use pallas_primitives::{alonzo, byron};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub mod block;
|
||||||
|
pub mod iter;
|
||||||
|
pub mod probe;
|
||||||
|
pub mod tx;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Era {
|
||||||
|
Byron,
|
||||||
|
Shelley,
|
||||||
|
Allegra, // time-locks
|
||||||
|
Mary, // multi-assets
|
||||||
|
Alonzo, // smart-contracts
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum MultiEraTx<'b> {
|
||||||
|
AlonzoCompatible(Box<alonzo::MintedTx<'b>>),
|
||||||
|
Byron(Box<byron::MintedTxPayload<'b>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum MultiEraBlock<'b> {
|
||||||
|
EpochBoundary(Box<byron::EbBlock>),
|
||||||
|
AlonzoCompatible(Box<alonzo::MintedBlock<'b>>),
|
||||||
|
Byron(Box<byron::MintedBlock<'b>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Invalid CBOR structure: {0}")]
|
||||||
|
InvalidCbor(String),
|
||||||
|
|
||||||
|
#[error("Unknown CBOR structure: {0}")]
|
||||||
|
UnknownCbor(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn invalid_cbor(error: impl Display) -> Self {
|
||||||
|
Error::InvalidCbor(format!("{}", error))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unknown_cbor(bytes: &[u8]) -> Self {
|
||||||
|
Error::UnknownCbor(hex::encode(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//! Heuristics for detecting cbor content without decoding
|
//! Lightweight inspection of block data without full CBOR decoding
|
||||||
|
|
||||||
use pallas_codec::minicbor::decode::{Token, Tokenizer};
|
use pallas_codec::minicbor::decode::{Token, Tokenizer};
|
||||||
|
|
||||||
|
|
@ -12,9 +12,9 @@ pub enum Outcome {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executes a very lightweight inspection of the initial tokens of the CBOR
|
// Executes a very lightweight inspection of the initial tokens of the CBOR
|
||||||
// payload and infers with a certain degree of confidence the type of Cardano
|
// block payload to extract the tag of the block wrapper which defines the era
|
||||||
// structure within.
|
// of the contained bytes.
|
||||||
pub fn probe_block_cbor_era(cbor: &[u8]) -> Outcome {
|
pub fn block_era(cbor: &[u8]) -> Outcome {
|
||||||
let mut tokenizer = Tokenizer::new(cbor);
|
let mut tokenizer = Tokenizer::new(cbor);
|
||||||
|
|
||||||
if !matches!(tokenizer.next(), Some(Ok(Token::Array(2)))) {
|
if !matches!(tokenizer.next(), Some(Ok(Token::Array(2)))) {
|
||||||
|
|
@ -44,7 +44,7 @@ mod tests {
|
||||||
let block_str = include_str!("../../test_data/genesis.block");
|
let block_str = include_str!("../../test_data/genesis.block");
|
||||||
let bytes = hex::decode(block_str).unwrap();
|
let bytes = hex::decode(block_str).unwrap();
|
||||||
|
|
||||||
let inference = probe_block_cbor_era(bytes.as_slice());
|
let inference = block_era(bytes.as_slice());
|
||||||
|
|
||||||
assert!(matches!(inference, Outcome::EpochBoundary));
|
assert!(matches!(inference, Outcome::EpochBoundary));
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ mod tests {
|
||||||
let block_str = include_str!("../../test_data/byron1.block");
|
let block_str = include_str!("../../test_data/byron1.block");
|
||||||
let bytes = hex::decode(block_str).unwrap();
|
let bytes = hex::decode(block_str).unwrap();
|
||||||
|
|
||||||
let inference = probe_block_cbor_era(bytes.as_slice());
|
let inference = block_era(bytes.as_slice());
|
||||||
|
|
||||||
assert!(matches!(inference, Outcome::Matched(Era::Byron)));
|
assert!(matches!(inference, Outcome::Matched(Era::Byron)));
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ mod tests {
|
||||||
let block_str = include_str!("../../test_data/shelley1.block");
|
let block_str = include_str!("../../test_data/shelley1.block");
|
||||||
let bytes = hex::decode(block_str).unwrap();
|
let bytes = hex::decode(block_str).unwrap();
|
||||||
|
|
||||||
let inference = probe_block_cbor_era(bytes.as_slice());
|
let inference = block_era(bytes.as_slice());
|
||||||
|
|
||||||
assert!(matches!(inference, Outcome::Matched(Era::Shelley)));
|
assert!(matches!(inference, Outcome::Matched(Era::Shelley)));
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +74,7 @@ mod tests {
|
||||||
let block_str = include_str!("../../test_data/allegra1.block");
|
let block_str = include_str!("../../test_data/allegra1.block");
|
||||||
let bytes = hex::decode(block_str).unwrap();
|
let bytes = hex::decode(block_str).unwrap();
|
||||||
|
|
||||||
let inference = probe_block_cbor_era(bytes.as_slice());
|
let inference = block_era(bytes.as_slice());
|
||||||
|
|
||||||
assert!(matches!(inference, Outcome::Matched(Era::Allegra)));
|
assert!(matches!(inference, Outcome::Matched(Era::Allegra)));
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ mod tests {
|
||||||
let block_str = include_str!("../../test_data/mary1.block");
|
let block_str = include_str!("../../test_data/mary1.block");
|
||||||
let bytes = hex::decode(block_str).unwrap();
|
let bytes = hex::decode(block_str).unwrap();
|
||||||
|
|
||||||
let inference = probe_block_cbor_era(bytes.as_slice());
|
let inference = block_era(bytes.as_slice());
|
||||||
|
|
||||||
assert!(matches!(inference, Outcome::Matched(Era::Mary)));
|
assert!(matches!(inference, Outcome::Matched(Era::Mary)));
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ mod tests {
|
||||||
let block_str = include_str!("../../test_data/alonzo1.block");
|
let block_str = include_str!("../../test_data/alonzo1.block");
|
||||||
let bytes = hex::decode(block_str).unwrap();
|
let bytes = hex::decode(block_str).unwrap();
|
||||||
|
|
||||||
let inference = probe_block_cbor_era(bytes.as_slice());
|
let inference = block_era(bytes.as_slice());
|
||||||
|
|
||||||
assert!(matches!(inference, Outcome::Matched(Era::Alonzo)));
|
assert!(matches!(inference, Outcome::Matched(Era::Alonzo)));
|
||||||
}
|
}
|
||||||
13
pallas-traverse/src/tx.rs
Normal file
13
pallas-traverse/src/tx.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
use pallas_primitives::{alonzo, byron};
|
||||||
|
|
||||||
|
use crate::MultiEraTx;
|
||||||
|
|
||||||
|
impl<'b> MultiEraTx<'b> {
|
||||||
|
pub fn from_byron(tx: byron::MintedTxPayload<'b>) -> Self {
|
||||||
|
Self::Byron(Box::new(tx))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_alonzo_compatible(tx: alonzo::MintedTx<'b>) -> Self {
|
||||||
|
Self::AlonzoCompatible(Box::new(tx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,5 +16,6 @@ authors = [
|
||||||
pallas-multiplexer = { version = "0.11.0-alpha.0", path = "../pallas-multiplexer/" }
|
pallas-multiplexer = { version = "0.11.0-alpha.0", path = "../pallas-multiplexer/" }
|
||||||
pallas-miniprotocols = { version = "0.11.0-alpha.0", path = "../pallas-miniprotocols/" }
|
pallas-miniprotocols = { version = "0.11.0-alpha.0", path = "../pallas-miniprotocols/" }
|
||||||
pallas-primitives = { version = "0.11.0-alpha.0", path = "../pallas-primitives/" }
|
pallas-primitives = { version = "0.11.0-alpha.0", path = "../pallas-primitives/" }
|
||||||
|
pallas-traverse = { version = "0.11.0-alpha.0", path = "../pallas-traverse/" }
|
||||||
pallas-crypto = { version = "0.11.0-alpha.0", path = "../pallas-crypto/" }
|
pallas-crypto = { version = "0.11.0-alpha.0", path = "../pallas-crypto/" }
|
||||||
pallas-codec = { version = "0.11.0-alpha.0", path = "../pallas-codec/" }
|
pallas-codec = { version = "0.11.0-alpha.0", path = "../pallas-codec/" }
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,6 @@
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use pallas_primitives as primitives;
|
pub use pallas_primitives as primitives;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use pallas_traverse as traverse;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue