From 520f3451538c1a1a17320de0d211a32fea917d3d Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Sat, 18 Jun 2022 10:44:33 -0300 Subject: [PATCH] Add Babbage primitives --- pallas-codec/src/utils.rs | 2 +- pallas-primitives/src/alonzo/model.rs | 70 ++-- pallas-primitives/src/babbage/mod.rs | 3 + pallas-primitives/src/babbage/model.rs | 524 +++++++++++++++++++++++++ pallas-primitives/src/lib.rs | 1 + test_data/babbage1.block | 1 + 6 files changed, 564 insertions(+), 37 deletions(-) create mode 100644 pallas-primitives/src/babbage/mod.rs create mode 100644 pallas-primitives/src/babbage/model.rs create mode 100644 test_data/babbage1.block diff --git a/pallas-codec/src/utils.rs b/pallas-codec/src/utils.rs index c487bb77..a98ebe22 100644 --- a/pallas-codec/src/utils.rs +++ b/pallas-codec/src/utils.rs @@ -229,7 +229,7 @@ where } /// Wraps a struct so that it is encoded/decoded as a cbor bytes -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, PartialOrd)] pub struct CborWrap(pub T); impl<'b, C, T> minicbor::Decode<'b, C> for CborWrap diff --git a/pallas-primitives/src/alonzo/model.rs b/pallas-primitives/src/alonzo/model.rs index dfd4e990..d98b21bd 100644 --- a/pallas-primitives/src/alonzo/model.rs +++ b/pallas-primitives/src/alonzo/model.rs @@ -43,24 +43,29 @@ pub struct HeaderBody { pub block_body_hash: Hash<32>, #[n(9)] - pub operational_cert: ByteVec, + pub operational_cert: OperationalCert, #[n(10)] - pub unknown_0: u64, + pub protocol: ProtocolVersion, +} - #[n(11)] - pub unknown_1: u64, +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +pub struct OperationalCert { + #[n(0)] + hot_vkey: ByteVec, - #[n(12)] - pub unknown_2: ByteVec, + #[n(1)] + sequence_number: u64, - #[n(13)] - pub protocol_version_major: u64, + #[n(2)] + kes_period: u64, - #[n(14)] - pub protocol_version_minor: u64, + #[n(3)] + sigma: ByteVec, } +pub type ProtocolVersion = (u64, u64); + #[derive(Encode, Decode, Debug, PartialEq)] pub struct KesSignature {} @@ -634,8 +639,6 @@ pub type CostModel = MaybeIndefArray; pub type CostMdls = KeyValuePairs; -pub type ProtocolVersion = (u32, u32); - #[derive(Encode, Decode, Debug, PartialEq, Clone)] #[cbor(map)] pub struct ProtocolParamUpdate { @@ -1146,11 +1149,13 @@ pub struct TransactionWitnessSet { #[derive(Encode, Decode, Debug, PartialEq, Clone)] #[cbor(map)] -pub struct AlonzoAuxiliaryData { +pub struct PostAlonzoAuxiliaryData { #[n(0)] pub metadata: Option, + #[n(1)] pub native_scripts: Option>, + #[n(2)] pub plutus_scripts: Option>, } @@ -1246,14 +1251,20 @@ pub type MetadatumLabel = AnyUInt; pub type Metadata = KeyValuePairs; +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +pub struct ShelleyMaAuxiliaryDAta { + #[n(0)] + transaction_metadata: Metadata, + + #[n(1)] + auxiliary_scripts: Option>, +} + #[derive(Debug, PartialEq, Clone)] pub enum AuxiliaryData { Shelley(Metadata), - ShelleyMa { - transaction_metadata: Metadata, - auxiliary_scripts: Option>, - }, - Alonzo(AlonzoAuxiliaryData), + ShelleyMa(ShelleyMaAuxiliaryDAta), + PostAlonzo(PostAlonzoAuxiliaryData), } impl<'b, C> minicbor::Decode<'b, C> for AuxiliaryData { @@ -1262,18 +1273,10 @@ impl<'b, C> minicbor::Decode<'b, C> for AuxiliaryData { minicbor::data::Type::Map | minicbor::data::Type::MapIndef => { Ok(AuxiliaryData::Shelley(d.decode_with(ctx)?)) } - minicbor::data::Type::Array => { - d.array()?; - let transaction_metadata = d.decode_with(ctx)?; - let auxiliary_scripts = d.decode_with(ctx)?; - Ok(AuxiliaryData::ShelleyMa { - transaction_metadata, - auxiliary_scripts, - }) - } + minicbor::data::Type::Array => Ok(AuxiliaryData::ShelleyMa(d.decode_with(ctx)?)), minicbor::data::Type::Tag => { d.tag()?; - Ok(AuxiliaryData::Alonzo(d.decode_with(ctx)?)) + Ok(AuxiliaryData::PostAlonzo(d.decode_with(ctx)?)) } _ => Err(minicbor::decode::Error::message( "Can't infer variant from data type for AuxiliaryData", @@ -1292,15 +1295,10 @@ impl minicbor::Encode for AuxiliaryData { AuxiliaryData::Shelley(m) => { e.encode_with(m, ctx)?; } - AuxiliaryData::ShelleyMa { - transaction_metadata, - auxiliary_scripts, - } => { - e.array(2)?; - e.encode_with(transaction_metadata, ctx)?; - e.encode_with(auxiliary_scripts, ctx)?; + AuxiliaryData::ShelleyMa(m) => { + e.encode_with(m, ctx)?; } - AuxiliaryData::Alonzo(v) => { + AuxiliaryData::PostAlonzo(v) => { // TODO: check if this is the correct tag e.tag(Tag::Unassigned(259))?; e.encode_with(v, ctx)?; diff --git a/pallas-primitives/src/babbage/mod.rs b/pallas-primitives/src/babbage/mod.rs new file mode 100644 index 00000000..4a7ebf60 --- /dev/null +++ b/pallas-primitives/src/babbage/mod.rs @@ -0,0 +1,3 @@ +mod model; + +pub use model::*; diff --git a/pallas-primitives/src/babbage/model.rs b/pallas-primitives/src/babbage/model.rs new file mode 100644 index 00000000..be42598b --- /dev/null +++ b/pallas-primitives/src/babbage/model.rs @@ -0,0 +1,524 @@ +//! Ledger primitives and cbor codec for the Alonzo era +//! +//! Handcrafted, idiomatic rust artifacts based on based on the [Babbage CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/babbage/test-suite/cddl-files/babbage.cddl) file in IOHK repo. + +use pallas_codec::minicbor::{bytes::ByteVec, Decode, Encode}; +use pallas_crypto::hash::Hash; + +use pallas_codec::utils::{CborWrap, KeepRaw, KeyValuePairs, MaybeIndefArray}; + +// required for derive attrs to work +use pallas_codec::minicbor; + +pub use crate::alonzo::VrfCert; + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +pub struct HeaderBody { + #[n(0)] + pub block_number: u64, + + #[n(1)] + pub slot: u64, + + #[n(2)] + pub prev_hash: Hash<32>, + + #[n(3)] + pub issuer_vkey: ByteVec, + + #[n(4)] + pub vrf_vkey: ByteVec, + + #[n(5)] + pub vrf_result: VrfCert, + + #[n(6)] + pub block_body_size: u64, + + #[n(7)] + pub block_body_hash: Hash<32>, + + #[n(8)] + pub operational_cert: OperationalCert, + + #[n(9)] + pub protocol_version: ProtocolVersion, +} + +pub use crate::alonzo::OperationalCert; + +pub use crate::alonzo::ProtocolVersion; + +pub use crate::alonzo::KesSignature; + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +pub struct Header { + #[n(0)] + pub header_body: HeaderBody, + + #[n(1)] + pub body_signature: ByteVec, +} + +pub use crate::alonzo::TransactionInput; + +pub use crate::alonzo::NonceVariant; + +pub use crate::alonzo::Nonce; + +pub use crate::alonzo::ScriptHash; + +pub use crate::alonzo::PolicyId; + +pub use crate::alonzo::AssetName; + +pub use crate::alonzo::Multiasset; + +pub use crate::alonzo::Mint; + +pub use crate::alonzo::Coin; + +pub use crate::alonzo::Value; + +pub use crate::alonzo::TransactionOutput as LegacyTransacionOutput; + +pub use crate::alonzo::PoolKeyhash; + +pub use crate::alonzo::Epoch; + +pub use crate::alonzo::Genesishash; + +pub use crate::alonzo::GenesisDelegateHash; + +pub use crate::alonzo::VrfKeyhash; + +pub use crate::alonzo::InstantaneousRewardSource; + +pub use crate::alonzo::InstantaneousRewardTarget; + +pub use crate::alonzo::MoveInstantaneousReward; + +pub use crate::alonzo::RewardAccount; + +pub use crate::alonzo::Port; + +pub use crate::alonzo::IPv4; + +pub use crate::alonzo::IPv6; + +pub use crate::alonzo::DnsName; + +pub use crate::alonzo::Relay; + +pub use crate::alonzo::PoolMetadataHash; + +pub use crate::alonzo::PoolMetadata; + +pub use crate::alonzo::AddrKeyhash; + +pub use crate::alonzo::Scripthash; + +pub use crate::alonzo::RationalNumber; + +pub use crate::alonzo::UnitInterval; + +pub use crate::alonzo::PositiveInterval; + +pub use crate::alonzo::StakeCredential; + +pub use crate::alonzo::Certificate; + +pub use crate::alonzo::NetworkId; + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(index_only)] +pub enum Language { + #[n(0)] + PlutusV1, + + #[n(1)] + PlutusV2, +} + +pub use crate::alonzo::CostModel; + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct CostMdls { + #[n(0)] + plutus_v1: CostModel, + + #[n(1)] + plutus_v2: CostModel, +} + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct ProtocolParamUpdate { + #[n(0)] + pub minfee_a: Option, + #[n(1)] + pub minfee_b: Option, + #[n(2)] + pub max_block_body_size: Option, + #[n(3)] + pub max_transaction_size: Option, + #[n(4)] + pub max_block_header_size: Option, + #[n(5)] + pub key_deposit: Option, + #[n(6)] + pub pool_deposit: Option, + #[n(7)] + pub maximum_epoch: Option, + #[n(8)] + pub desired_number_of_stake_pools: Option, + #[n(9)] + pub pool_pledge_influence: Option, + #[n(10)] + pub expansion_rate: Option, + #[n(11)] + pub treasury_growth_rate: Option, + + #[n(14)] + pub protocol_version: Option, + #[n(16)] + pub min_pool_cost: Option, + #[n(17)] + pub ada_per_utxo_byte: Option, + #[n(18)] + pub cost_models_for_script_languages: Option, + #[n(19)] + pub execution_costs: Option, + #[n(20)] + pub max_tx_ex_units: Option, + #[n(21)] + pub max_block_ex_units: Option, + #[n(22)] + pub max_value_size: Option, + #[n(23)] + pub collateral_percentage: Option, + #[n(24)] + pub max_collateral_inputs: Option, +} + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +pub struct Update { + #[n(0)] + pub proposed_protocol_parameter_updates: KeyValuePairs, + + #[n(1)] + pub epoch: Epoch, +} + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct TransactionBody { + #[n(0)] + pub inputs: MaybeIndefArray, + + #[n(1)] + pub outputs: MaybeIndefArray, + + #[n(2)] + pub fee: u64, + + #[n(3)] + pub ttl: Option, + + #[n(4)] + pub certificates: Option>, + + #[n(5)] + pub withdrawals: Option>, + + #[n(6)] + pub update: Option, + + #[n(7)] + pub auxiliary_data_hash: Option, + + #[n(8)] + pub validity_interval_start: Option, + + #[n(9)] + pub mint: Option>, + + #[n(11)] + pub script_data_hash: Option>, + + #[n(13)] + pub collateral: Option>, + + #[n(14)] + pub required_signers: Option>, + + #[n(15)] + pub network_id: Option, + + #[n(16)] + collateral_return: TransactionOutput, + + #[n(17)] + total_collateral: Coin, + + #[n(18)] + reference_inputs: MaybeIndefArray, +} + +#[derive(Debug, PartialEq, Clone)] +pub enum TransactionOutput { + Legacy(LegacyTransacionOutput), + PostAlonzo(PostAlonzoTransactionOutput), +} + +impl<'b, C> minicbor::Decode<'b, C> for TransactionOutput { + fn decode( + d: &mut minicbor::Decoder<'b>, + _ctx: &mut C, + ) -> Result { + match d.datatype()? { + minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => { + Ok(TransactionOutput::Legacy(d.decode()?)) + } + minicbor::data::Type::Map | minicbor::data::Type::MapIndef => { + Ok(TransactionOutput::PostAlonzo(d.decode()?)) + } + _ => Err(minicbor::decode::Error::message( + "invalid type for transaction output struct", + )), + } + } +} + +impl minicbor::Encode for TransactionOutput { + fn encode( + &self, + e: &mut minicbor::Encoder, + ctx: &mut C, + ) -> Result<(), minicbor::encode::Error> { + match self { + TransactionOutput::Legacy(x) => x.encode(e, ctx), + TransactionOutput::PostAlonzo(x) => x.encode(e, ctx), + } + } +} + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct PostAlonzoTransactionOutput { + #[n(0)] + address: ByteVec, + + #[n(1)] + value: Value, + + #[n(2)] + datum_option: Option, + + #[n(3)] + script_ref: Option, +} + +pub use crate::alonzo::VKeyWitness; + +pub use crate::alonzo::NativeScript; + +pub use crate::alonzo::PlutusScript as PlutusV1Script; + +pub type PlutusV2Script = ByteVec; + +pub use crate::alonzo::BigInt; + +pub use crate::alonzo::PlutusData; + +pub use crate::alonzo::Constr; + +pub use crate::alonzo::ExUnits; + +pub use crate::alonzo::ExUnitPrices; + +pub use crate::alonzo::RedeemerTag; + +pub use crate::alonzo::Redeemer; + +pub use crate::alonzo::BootstrapWitness; + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct TransactionWitnessSet { + #[n(0)] + pub vkeywitness: Option>, + + #[n(1)] + pub native_script: Option>, + + #[n(2)] + pub bootstrap_witness: Option>, + + #[n(3)] + pub plutus_v1_script: Option>, + + #[n(4)] + pub plutus_data: Option>, + + #[n(5)] + pub redeemer: Option>, + + #[n(6)] + pub plutus_v2_script: Option>, +} + +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +#[cbor(map)] +pub struct PostAlonzoAuxiliaryData { + #[n(0)] + pub metadata: Option, + + #[n(1)] + pub native_scripts: Option>, + + #[n(2)] + pub plutus_v1_scripts: Option>, + + #[n(3)] + pub plutus_v2_scripts: Option>, +} + +pub type DatumHash = Hash<32>; + +pub type Data = CborWrap; + +// datum_option = [ 0, $hash32 // 1, data ] +#[derive(Encode, Decode, Debug, PartialEq, Clone)] +pub enum DatumOption { + #[n(0)] + Hash(#[n(0)] Hash<32>), + + #[n(1)] + Data(#[n(0)] Data), +} + +// script_ref = #6.24(bytes .cbor script) +pub type ScriptRef = CborWrap