refactor: Re-organize and clean-up pallas-primitives (#523)

* Re-organize and clean-up pallas-primitives

  Namely:

  - Move _common_ (i.e. era-independent) types and structures up to the
    `lib` module; to be shared across all eras. If any of those deviate
    in a subsequent era, it is easy to bring them down and define new
    types from the point of divergence onward. This simplifies the scope
    of each era-specific module and make them slightly easier to
    navigate.

    Note that, each era module still re-export all of the common types
    that's relevant to that particular era. So technically, this
    reorganization doesn't really change anything for callers/users of
    the library.

  - Rename `Scripthash` to `ScriptHash`. Before this commit, both
    actually existed as `ScriptHash` was introduced with the Conway era.
    Yet, they refer to the same thing, so the duplication is simply
    confusing.

  - Rename `One` / `Two` constructors for `NetworkId` to `Testnet` and
    `Mainnet` respectively. Also defined idiomatic `From` & `TryFrom`
    implementation for conversion to and from `u8`. This is a lot let
    confusing!

  - Generalize `PlutusScript` with a constant generic, to avoid
    repetition for each plutus script generated for specific version.
    Note that a distinction is still _necessary_ if we want to provie
    out-of-the-box serialisers for Plutus scripts, which are serialised
    with a tag prefix depending on the language. All else apart, they
    are strictly similar types.

  - Rename `CostMdls` to `CostModels`. Because, common.

  - Rename `plutus_script` to `plutus_v1_script` in the Alonzo's witness
    set, for consistency with other eras.

* Fix ordering of ScriptHash variants.

  This is an odd one. See the note.

* Bump minicbor to v0.25.1

* Add aliases with deprecation warnings to various fields and types.

* revert renaming plutus_script to plutus_v1_script in Alonzo witness

  See https://github.com/txpipe/pallas/pull/523#discussion_r1807329742
This commit is contained in:
Matthias Benkort 2024-10-22 13:57:21 +02:00 committed by GitHub
parent 4871342a8d
commit 969d5612b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 972 additions and 1071 deletions

View file

@ -2,8 +2,8 @@
use crate::utils::{
add_minted_value, add_values, aux_data_from_alonzo_minted_tx, compute_native_script_hash,
compute_plutus_script_hash, empty_value, get_alonzo_comp_tx_size, get_lovelace_from_alonzo_val,
get_network_id_value, get_payment_part, get_shelley_address, get_val_size_in_words,
compute_plutus_v1_script_hash, empty_value, get_alonzo_comp_tx_size,
get_lovelace_from_alonzo_val, get_payment_part, get_shelley_address, get_val_size_in_words,
mk_alonzo_vk_wits_check_list, values_are_equal, verify_signature,
AlonzoError::*,
AlonzoProtParams, UTxOs,
@ -159,7 +159,7 @@ fn check_min_fee(
fn presence_of_plutus_scripts(mtx: &MintedTx) -> bool {
let minted_witness_set: &MintedWitnessSet = &mtx.transaction_witness_set;
match &minted_witness_set.plutus_script {
Some(plutus_scripts) => !plutus_scripts.is_empty(),
Some(plutus_v1_scripts) => !plutus_v1_scripts.is_empty(),
None => false,
}
}
@ -355,7 +355,7 @@ fn check_tx_outs_network_id(tx_body: &TransactionBody, network_id: &u8) -> Valid
// global network ID.
fn check_tx_network_id(tx_body: &TransactionBody, network_id: &u8) -> ValidationResult {
if let Some(tx_network_id) = tx_body.network_id {
if get_network_id_value(tx_network_id) != *network_id {
if u8::from(tx_network_id) != *network_id {
return Err(Alonzo(TxWrongNetworkID));
}
}
@ -402,11 +402,11 @@ fn check_witness_set(mtx: &MintedTx, utxos: &UTxOs) -> ValidationResult {
Some(scripts) => scripts.clone().iter().map(|x| x.clone().unwrap()).collect(),
None => Vec::new(),
};
let plutus_scripts: Vec<PlutusScript> = match &tx_wits.plutus_script {
let plutus_v1_scripts: Vec<PlutusScript<1>> = match &tx_wits.plutus_script {
Some(scripts) => scripts.clone(),
None => Vec::new(),
};
check_needed_scripts_are_included(tx_body, utxos, &native_scripts, &plutus_scripts)?;
check_needed_scripts_are_included(tx_body, utxos, &native_scripts, &plutus_v1_scripts)?;
check_datums(tx_body, utxos, &tx_wits.plutus_data)?;
check_redeemers(tx_body, tx_wits, utxos)?;
check_required_signers(&tx_body.required_signers, vkey_wits, tx_hash)?;
@ -420,21 +420,23 @@ fn check_needed_scripts_are_included(
tx_body: &TransactionBody,
utxos: &UTxOs,
native_scripts: &[NativeScript],
plutus_scripts: &[PlutusScript],
plutus_v1_scripts: &[PlutusScript<1>],
) -> ValidationResult {
let mut native_scripts: Vec<(bool, NativeScript)> =
native_scripts.iter().map(|x| (false, x.clone())).collect();
let mut plutus_scripts: Vec<(bool, PlutusScript)> =
plutus_scripts.iter().map(|x| (false, x.clone())).collect();
check_script_inputs(tx_body, &mut native_scripts, &mut plutus_scripts, utxos)?;
check_minting_policies(tx_body, &mut native_scripts, &mut plutus_scripts)?;
let mut plutus_v1_scripts: Vec<(bool, PlutusScript<1>)> = plutus_v1_scripts
.iter()
.map(|x| (false, x.clone()))
.collect();
check_script_inputs(tx_body, &mut native_scripts, &mut plutus_v1_scripts, utxos)?;
check_minting_policies(tx_body, &mut native_scripts, &mut plutus_v1_scripts)?;
for (native_script_covered, _) in native_scripts.iter() {
if !native_script_covered {
return Err(Alonzo(UnneededNativeScript));
}
}
for (plutus_script_covered, _) in plutus_scripts.iter() {
if !plutus_script_covered {
for (plutus_v1_script_covered, _) in plutus_v1_scripts.iter() {
if !plutus_v1_script_covered {
return Err(Alonzo(UnneededPlutusScript));
}
}
@ -554,7 +556,7 @@ fn mk_plutus_script_redeemer_pointers(
for (index, input) in sorted_inputs.iter().enumerate() {
if let Some(script_hash) = get_script_hash_from_input(input, utxos) {
for plutus_script in plutus_scripts.iter() {
let hashed_script: PolicyId = compute_plutus_script_hash(plutus_script);
let hashed_script: PolicyId = compute_plutus_v1_script_hash(plutus_script);
if script_hash == hashed_script {
res.push(RedeemerPointer {
tag: RedeemerTag::Spend,
@ -569,7 +571,8 @@ fn mk_plutus_script_redeemer_pointers(
let sorted_policies: Vec<PolicyId> = sort_policies(minted_value);
for (index, policy) in sorted_policies.iter().enumerate() {
for plutus_script in plutus_scripts.iter() {
let hashed_script: PolicyId = compute_plutus_script_hash(plutus_script);
let hashed_script: PolicyId =
compute_plutus_v1_script_hash(plutus_script);
if *policy == hashed_script {
res.push(RedeemerPointer {
tag: RedeemerTag::Mint,
@ -626,7 +629,7 @@ fn redeemer_pointers_coincide(
fn check_script_inputs(
tx_body: &TransactionBody,
native_scripts: &mut [(bool, NativeScript)],
plutus_scripts: &mut [(bool, PlutusScript)],
plutus_v1_scripts: &mut [(bool, PlutusScript<1>)],
utxos: &UTxOs,
) -> ValidationResult {
let mut inputs: Vec<(bool, ScriptHash)> = get_script_hashes(tx_body, utxos);
@ -638,8 +641,8 @@ fn check_script_inputs(
*native_script_covered = true;
}
}
for (plutus_script_covered, plutus_script) in plutus_scripts.iter_mut() {
let hashed_script: PolicyId = compute_plutus_script_hash(plutus_script);
for (plutus_script_covered, plutus_v1_script) in plutus_v1_scripts.iter_mut() {
let hashed_script: PolicyId = compute_plutus_v1_script_hash(plutus_v1_script);
if *input_script_hash == hashed_script {
*input_script_covered = true;
*plutus_script_covered = true;
@ -678,7 +681,7 @@ fn get_script_hash_from_input(input: &TransactionInput, utxos: &UTxOs) -> Option
fn check_minting_policies(
tx_body: &TransactionBody,
native_scripts: &mut [(bool, NativeScript)],
plutus_scripts: &mut [(bool, PlutusScript)],
plutus_v1_scripts: &mut [(bool, PlutusScript<1>)],
) -> ValidationResult {
match &tx_body.mint {
None => Ok(()),
@ -693,8 +696,8 @@ fn check_minting_policies(
*native_script_covered = true;
}
}
for (plutus_script_covered, plutus_script) in plutus_scripts.iter_mut() {
let hashed_script: PolicyId = compute_plutus_script_hash(plutus_script);
for (plutus_script_covered, plutus_v1_script) in plutus_v1_scripts.iter_mut() {
let hashed_script: PolicyId = compute_plutus_v1_script_hash(plutus_v1_script);
if *policy == hashed_script {
*policy_covered = true;
*plutus_script_covered = true;
@ -923,18 +926,18 @@ fn check_minting(tx_body: &TransactionBody, mtx: &MintedTx) -> ValidationResult
.map(|x| x.clone().unwrap())
.collect(),
};
let plutus_script_wits: Vec<PlutusScript> =
let plutus_v1_script_wits: Vec<PlutusScript<1>> =
match &mtx.transaction_witness_set.plutus_script {
None => Vec::new(),
Some(plutus_script_wits) => plutus_script_wits.clone(),
Some(plutus_v1_script_wits) => plutus_v1_script_wits.clone(),
};
for (policy, _) in minted_value.iter() {
if native_script_wits
.iter()
.all(|native_script| compute_native_script_hash(native_script) != *policy)
&& plutus_script_wits
.iter()
.all(|plutus_script| compute_plutus_script_hash(plutus_script) != *policy)
&& plutus_v1_script_wits.iter().all(|plutus_v1_script| {
compute_plutus_v1_script_hash(plutus_v1_script) != *policy
})
{
return Err(Alonzo(MintingLacksPolicy));
}

View file

@ -2,10 +2,10 @@
use crate::utils::{
add_minted_value, add_values, aux_data_from_babbage_minted_tx, compute_native_script_hash,
compute_plutus_script_hash, compute_plutus_v2_script_hash, empty_value, get_babbage_tx_size,
get_lovelace_from_alonzo_val, get_network_id_value, get_payment_part, get_shelley_address,
get_val_size_in_words, is_byron_address, lovelace_diff_or_fail, mk_alonzo_vk_wits_check_list,
values_are_equal, verify_signature,
compute_plutus_v1_script_hash, compute_plutus_v2_script_hash, empty_value, get_babbage_tx_size,
get_lovelace_from_alonzo_val, get_payment_part, get_shelley_address, get_val_size_in_words,
is_byron_address, lovelace_diff_or_fail, mk_alonzo_vk_wits_check_list, values_are_equal,
verify_signature,
BabbageError::*,
BabbageProtParams, UTxOs,
ValidationError::{self, *},
@ -16,15 +16,14 @@ use pallas_codec::{
minicbor::{encode, Encoder},
utils::{Bytes, KeepRaw},
};
use pallas_crypto::hash::Hash;
use pallas_primitives::{
alonzo::{RedeemerPointer, RedeemerTag},
babbage::{
AddrKeyhash, Language, Mint, MintedTransactionBody, MintedTransactionOutput, MintedTx,
MintedWitnessSet, NativeScript, PlutusData, PlutusV1Script, PlutusV2Script, PolicyId,
PseudoDatumOption, PseudoScript, PseudoTransactionOutput, Redeemer, RequiredSigners,
TransactionInput, VKeyWitness, Value,
Language, Mint, MintedTransactionBody, MintedTransactionOutput, MintedTx, MintedWitnessSet,
NativeScript, PseudoDatumOption, PseudoScript, PseudoTransactionOutput, Redeemer,
RequiredSigners, VKeyWitness, Value,
},
AddrKeyhash, Hash, PlutusData, PlutusScript, PolicyId, TransactionInput,
};
use pallas_traverse::{MultiEraInput, MultiEraOutput, OriginalHash};
use std::ops::Deref;
@ -166,11 +165,11 @@ fn check_min_fee(
fn presence_of_plutus_scripts(mtx: &MintedTx) -> bool {
let minted_witness_set: &MintedWitnessSet = &mtx.transaction_witness_set;
let plutus_v1_scripts: &[PlutusV1Script] = &minted_witness_set
let plutus_v1_scripts: &[PlutusScript<1>] = &minted_witness_set
.plutus_v1_script
.clone()
.unwrap_or_default();
let plutus_v2_scripts: &[PlutusV2Script] = &minted_witness_set
let plutus_v2_scripts: &[PlutusScript<2>] = &minted_witness_set
.plutus_v2_script
.clone()
.unwrap_or_default();
@ -401,7 +400,7 @@ fn check_tx_outs_network_id(tx_body: &MintedTransactionBody, network_id: &u8) ->
// global network ID.
fn check_tx_network_id(tx_body: &MintedTransactionBody, network_id: &u8) -> ValidationResult {
if let Some(tx_network_id) = tx_body.network_id {
if get_network_id_value(tx_network_id) != *network_id {
if u8::from(tx_network_id) != *network_id {
return Err(Babbage(TxWrongNetworkID));
}
}
@ -449,12 +448,12 @@ fn check_minting(tx_body: &MintedTransactionBody, mtx: &MintedTx) -> ValidationR
.map(|x| x.clone().unwrap())
.collect(),
};
let v1_script_wits: Vec<PlutusV1Script> =
let v1_script_wits: Vec<PlutusScript<1>> =
match &mtx.transaction_witness_set.plutus_v1_script {
None => Vec::new(),
Some(v1_script_wits) => v1_script_wits.clone(),
};
let v2_script_wits: Vec<PlutusV2Script> =
let v2_script_wits: Vec<PlutusScript<2>> =
match &mtx.transaction_witness_set.plutus_v2_script {
None => Vec::new(),
Some(v2_script_wits) => v2_script_wits.clone(),
@ -465,7 +464,7 @@ fn check_minting(tx_body: &MintedTransactionBody, mtx: &MintedTx) -> ValidationR
.all(|script| compute_native_script_hash(script) != *policy)
&& v1_script_wits
.iter()
.all(|script| compute_plutus_script_hash(script) != *policy)
.all(|script| compute_plutus_v1_script_hash(script) != *policy)
&& v2_script_wits
.iter()
.all(|script| compute_plutus_v2_script_hash(script) != *policy)
@ -500,7 +499,7 @@ fn check_witness_set(mtx: &MintedTx, utxos: &UTxOs) -> ValidationResult {
Some(scripts) => scripts
.clone()
.iter()
.map(compute_plutus_script_hash)
.map(compute_plutus_v1_script_hash)
.collect(),
None => Vec::new(),
};

View file

@ -12,12 +12,12 @@ use pallas_codec::{
use pallas_crypto::key::ed25519::{PublicKey, Signature};
use pallas_primitives::{
alonzo::{
AddrKeyhash, AssetName, AuxiliaryData, Coin, Epoch, GenesisDelegateHash, Genesishash,
MintedTx as AlonzoMintedTx, Multiasset, NativeScript, NetworkId, PlutusScript, PolicyId,
PoolKeyhash, PoolMetadata, Relay, RewardAccount, StakeCredential, TransactionIndex,
UnitInterval, VKeyWitness, Value, VrfKeyhash,
AuxiliaryData, MintedTx as AlonzoMintedTx, Multiasset, NativeScript, VKeyWitness, Value,
},
babbage::{MintedTx as BabbageMintedTx, PlutusV2Script},
babbage::MintedTx as BabbageMintedTx,
AddrKeyhash, AssetName, Coin, Epoch, GenesisDelegateHash, Genesishash, NetworkId, PlutusScript,
PolicyId, PoolKeyhash, PoolMetadata, Relay, RewardAccount, StakeCredential, TransactionIndex,
UnitInterval, VrfKeyhash,
};
use pallas_traverse::{time::Slot, MultiEraInput, MultiEraOutput};
use std::collections::HashMap;
@ -267,11 +267,9 @@ pub fn get_lovelace_from_alonzo_val(val: &Value) -> Coin {
}
}
#[deprecated(since = "0.31.0", note = "use `u8::from(...)` instead")]
pub fn get_network_id_value(network_id: NetworkId) -> u8 {
match network_id {
NetworkId::One => 0,
NetworkId::Two => 1,
}
u8::from(network_id)
}
pub fn mk_alonzo_vk_wits_check_list(
@ -337,13 +335,18 @@ pub fn compute_native_script_hash(script: &NativeScript) -> PolicyId {
pallas_crypto::hash::Hasher::<224>::hash(&payload)
}
pub fn compute_plutus_script_hash(script: &PlutusScript) -> PolicyId {
#[deprecated(since = "0.31.0", note = "use `compute_plutus_v1_script_hash` instead")]
pub fn compute_plutus_script_hash(script: &PlutusScript<1>) -> PolicyId {
compute_plutus_v1_script_hash(script)
}
pub fn compute_plutus_v1_script_hash(script: &PlutusScript<1>) -> PolicyId {
let mut payload: Vec<u8> = Vec::from(script.as_ref());
payload.insert(0, 1);
pallas_crypto::hash::Hasher::<224>::hash(&payload)
}
pub fn compute_plutus_v2_script_hash(script: &PlutusV2Script) -> PolicyId {
pub fn compute_plutus_v2_script_hash(script: &PlutusScript<2>) -> PolicyId {
let mut payload: Vec<u8> = Vec::from(script.as_ref());
payload.insert(0, 2);
pallas_crypto::hash::Hasher::<224>::hash(&payload)
@ -375,7 +378,8 @@ pub struct DState {
pub inst_rewards: InstantaneousRewards,
}
// Essentially part of the `PoolRegistration` component of `Certificate` at alonzo/src/model.rs
// Essentially part of the `PoolRegistration` component of `Certificate` at
// alonzo/src/model.rs
#[derive(Clone, Debug)]
pub struct PoolParam {
pub vrf_keyhash: VrfKeyhash,

View file

@ -2,10 +2,11 @@
//! era.
use pallas_primitives::{
alonzo::{
Coin, CostMdls, ExUnitPrices, ExUnits, Nonce, ProtocolVersion, RationalNumber, UnitInterval,
Coin, CostModels, ExUnitPrices, ExUnits, Nonce, ProtocolVersion, RationalNumber,
UnitInterval,
},
babbage::CostMdls as BabbageCostMdls,
conway::{CostMdls as ConwayCostMdls, Epoch},
babbage::CostModels as BabbageCostModels,
conway::{CostModels as ConwayCostModels, Epoch},
};
#[allow(clippy::large_enum_variant)]
@ -100,7 +101,7 @@ pub struct AlonzoProtParams {
pub protocol_version: ProtocolVersion,
pub min_pool_cost: Coin,
pub ada_per_utxo_byte: Coin,
pub cost_models_for_script_languages: CostMdls,
pub cost_models_for_script_languages: CostModels,
pub execution_costs: ExUnitPrices,
pub max_tx_ex_units: ExUnits,
pub max_block_ex_units: ExUnits,
@ -128,7 +129,7 @@ pub struct BabbageProtParams {
pub protocol_version: ProtocolVersion,
pub min_pool_cost: Coin,
pub ada_per_utxo_byte: Coin,
pub cost_models_for_script_languages: BabbageCostMdls,
pub cost_models_for_script_languages: BabbageCostModels,
pub execution_costs: ExUnitPrices,
pub max_tx_ex_units: ExUnits,
pub max_block_ex_units: ExUnits,
@ -156,7 +157,7 @@ pub struct ConwayProtParams {
pub protocol_version: ProtocolVersion,
pub min_pool_cost: Coin,
pub ada_per_utxo_byte: Coin,
pub cost_models_for_script_languages: ConwayCostMdls,
pub cost_models_for_script_languages: ConwayCostModels,
pub execution_costs: ExUnitPrices,
pub max_tx_ex_units: ExUnits,
pub max_block_ex_units: ExUnits,

View file

@ -1152,9 +1152,7 @@ mod alonzo_tests {
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/alonzo1.tx"));
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
let mut tx_body: TransactionBody = (*mtx.transaction_body).clone();
// Note that NetworkId::One maps to 0 through
// crate::utils::get_network_id_value, which is not correct in mainnet.
tx_body.network_id = Some(NetworkId::One);
tx_body.network_id = Some(NetworkId::Testnet);
let mut tx_buf: Vec<u8> = Vec::new();
let _ = encode(tx_body, &mut tx_buf);
mtx.transaction_body =

File diff suppressed because one or more lines are too long

View file

@ -19,7 +19,7 @@ default = []
[dependencies]
hex = "0.4.3"
minicbor = { version = "0.20", features = ["std", "half", "derive"] }
minicbor = { version = "0.25.1", features = ["std", "half", "derive"] }
num-bigint = { version = "0.4.4", optional = true }
serde = { version = "1.0.143", features = ["derive"] }
thiserror = "1.0.39"

View file

@ -1,5 +1,5 @@
use minicbor::{
data::{Tag, Type},
data::{IanaTag, Tag, Type},
decode::Error,
Decode, Encode,
};
@ -543,7 +543,7 @@ where
minicbor::encode::Error::message("error encoding cbor-wrapped structure")
})?;
e.tag(Tag::Cbor)?;
e.tag(IanaTag::Cbor)?;
e.bytes(&buf)?;
Ok(())
@ -587,7 +587,7 @@ where
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(T))?;
e.tag(Tag::new(T))?;
e.encode_with(&self.0, ctx)?;
Ok(())
@ -741,7 +741,7 @@ where
if d.datatype()? == Type::Tag {
let found_tag = d.tag()?;
if found_tag != Tag::Unassigned(TAG_SET) {
if found_tag != Tag::new(TAG_SET) {
return Err(Error::message(format!("Unrecognised tag: {found_tag:?}")));
}
}
@ -759,7 +759,7 @@ where
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(TAG_SET))?;
e.tag(Tag::new(TAG_SET))?;
e.encode_with(&self.0, ctx)?;
Ok(())
@ -824,7 +824,7 @@ where
if d.datatype()? == Type::Tag {
let found_tag = d.tag()?;
if found_tag != Tag::Unassigned(TAG_SET) {
if found_tag != Tag::new(TAG_SET) {
return Err(Error::message(format!("Unrecognised tag: {found_tag:?}")));
}
}
@ -848,7 +848,7 @@ where
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(TAG_SET))?;
e.tag(Tag::new(TAG_SET))?;
e.encode_with(&self.0, ctx)?;
Ok(())

View file

@ -73,7 +73,7 @@ impl From<CostModel> for pallas_primitives::alonzo::CostModel {
#[derive(Deserialize, Clone)]
pub struct CostModelPerLanguage(HashMap<Language, CostModel>);
impl From<CostModelPerLanguage> for pallas_primitives::alonzo::CostMdls {
impl From<CostModelPerLanguage> for pallas_primitives::alonzo::CostModels {
fn from(value: CostModelPerLanguage) -> Self {
let inner = value
.0

View file

@ -1,4 +1,4 @@
use pallas_codec::minicbor::{data::Tag, decode, encode, Decode, Decoder, Encode, Encoder};
use pallas_codec::minicbor::{data::IanaTag, decode, encode, Decode, Decoder, Encode, Encoder};
use super::Message;
@ -29,7 +29,7 @@ impl Encode<()> for Message {
}
Message::Block { body } => {
e.array(2)?.u16(4)?;
e.tag(Tag::Cbor)?;
e.tag(IanaTag::Cbor)?;
e.bytes(body)?;
Ok(())
}

View file

@ -186,10 +186,10 @@ impl Encode<()> for HeaderContent {
return Err(Error::message("header variant 0 but no byron prefix"));
}
e.tag(minicbor::data::Tag::Cbor)?;
e.tag(minicbor::data::IanaTag::Cbor)?;
e.bytes(&self.cbor)?;
} else {
e.tag(minicbor::data::Tag::Cbor)?;
e.tag(minicbor::data::IanaTag::Cbor)?;
e.bytes(&self.cbor)?;
}
@ -211,7 +211,7 @@ impl Encode<()> for BlockContent {
e: &mut Encoder<W>,
_ctx: &mut (),
) -> Result<(), encode::Error<W::Error>> {
e.tag(minicbor::data::Tag::Cbor)?;
e.tag(minicbor::data::IanaTag::Cbor)?;
e.bytes(&self.0)?;
Ok(())

View file

@ -100,7 +100,7 @@ impl Encode<()> for BlockQuery {
if !pools.is_empty() {
e.array(1)?;
e.tag(Tag::Unassigned(258))?;
e.tag(Tag::new(258))?;
}
e.encode(pools)?;
@ -330,7 +330,7 @@ impl<C> minicbor::encode::Encode<C> for RationalNumber {
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(30))?;
e.tag(Tag::new(30))?;
e.array(2)?;
e.encode_with(self.numerator, ctx)?;
e.encode_with(self.denominator, ctx)?;

View file

@ -1,4 +1,4 @@
use pallas_codec::minicbor::data::Tag;
use pallas_codec::minicbor::data::IanaTag;
use pallas_codec::minicbor::{decode, encode, Decode, Decoder, Encode, Encoder};
use crate::miniprotocols::localtxsubmission::{EraTx, Message, RejectReason};
@ -78,7 +78,7 @@ impl<'b> Decode<'b, ()> for EraTx {
d.array()?;
let era = d.u16()?;
let tag = d.tag()?;
if tag != Tag::Cbor {
if tag != IanaTag::Cbor.tag() {
return Err(decode::Error::message("Expected encoded CBOR data item"));
}
Ok(EraTx(era, d.bytes()?.to_vec()))
@ -93,7 +93,7 @@ impl Encode<()> for EraTx {
) -> Result<(), encode::Error<W::Error>> {
e.array(2)?;
e.u16(self.0)?;
e.tag(Tag::Cbor)?;
e.tag(IanaTag::Cbor)?;
e.bytes(&self.1)?;
Ok(())
}

View file

@ -1,4 +1,4 @@
use pallas_codec::minicbor::{data::Tag, decode, encode, Decode, Decoder, Encode, Encoder};
use pallas_codec::minicbor::{data::IanaTag, decode, encode, Decode, Decoder, Encode, Encoder};
use super::{
protocol::{Message, TxIdAndSize},
@ -89,7 +89,7 @@ impl<'b> Decode<'b, ()> for EraTxBody {
d.array()?;
let era = d.u16()?;
let tag = d.tag()?;
if tag != Tag::Cbor {
if tag != IanaTag::Cbor.tag() {
return Err(decode::Error::message("Expected encoded CBOR data item"));
}
Ok(EraTxBody(era, d.bytes()?.to_vec()))
@ -104,7 +104,7 @@ impl Encode<()> for EraTxBody {
) -> Result<(), encode::Error<W::Error>> {
e.array(2)?;
e.u16(self.0)?;
e.tag(Tag::Cbor)?;
e.tag(IanaTag::Cbor)?;
e.bytes(&self.1)?;
Ok(())
}

View file

@ -3,18 +3,17 @@
//! Handcrafted, idiomatic rust artifacts based on based on the [Alonzo CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl) file in IOHK repo.
use serde::{Deserialize, Serialize};
use std::{fmt, hash::Hash as StdHash, ops::Deref};
use pallas_codec::minicbor::{data::Tag, Decode, Encode};
use pallas_crypto::hash::Hash;
use pallas_codec::minicbor::{self, data::Tag, Decode, Encode};
use pallas_codec::utils::{Bytes, Int, KeepRaw, KeyValuePairs, MaybeIndefArray, Nullable};
// required for derive attrs to work
use pallas_codec::minicbor;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct VrfCert(#[n(0)] pub Bytes, #[n(1)] pub Bytes);
pub use crate::{
plutus_data::*, AddrKeyhash, AssetName, Bytes, Coin, CostModel, DatumHash, DnsName, Epoch,
ExUnitPrices, ExUnits, GenesisDelegateHash, Genesishash, Hash, IPv4, IPv6, Int, KeepRaw,
KeyValuePairs, MaybeIndefArray, Metadata, Metadatum, MetadatumLabel, NetworkId, Nonce,
NonceVariant, Nullable, PlutusScript, PolicyId, PoolKeyhash, PoolMetadata, PoolMetadataHash,
Port, PositiveInterval, ProtocolVersion, RationalNumber, Relay, RewardAccount, ScriptHash,
StakeCredential, TransactionIndex, TransactionInput, UnitInterval, VrfCert, VrfKeyhash,
};
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct HeaderBody {
@ -64,11 +63,6 @@ pub struct HeaderBody {
pub protocol_minor: u64,
}
pub type ProtocolVersion = (u64, u64);
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq)]
pub struct KesSignature {}
pub type MintedHeaderBody<'a> = KeepRaw<'a, HeaderBody>;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
@ -100,50 +94,10 @@ impl<'a> From<MintedHeaderBody<'a>> for HeaderBody {
}
}
#[derive(
Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, StdHash,
)]
pub struct TransactionInput {
#[n(0)]
pub transaction_id: Hash<32>,
#[n(1)]
pub index: u64,
}
// $nonce /= [ 0 // 1, bytes .size 32 ]
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(index_only)]
pub enum NonceVariant {
#[n(0)]
NeutralNonce,
#[n(1)]
Nonce,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct Nonce {
#[n(0)]
pub variant: NonceVariant,
#[n(1)]
pub hash: Option<Hash<32>>,
}
pub type ScriptHash = Hash<28>;
pub type PolicyId = Hash<28>;
pub type AssetName = Bytes;
pub type Multiasset<A> = KeyValuePairs<PolicyId, KeyValuePairs<AssetName, A>>;
pub type Mint = Multiasset<i64>;
pub type Coin = u64;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Value {
Coin(Coin),
@ -201,15 +155,9 @@ pub struct TransactionOutput {
pub amount: Value,
#[n(2)]
pub datum_hash: Option<Hash<32>>,
pub datum_hash: Option<DatumHash>,
}
pub type PoolKeyhash = Hash<28>;
pub type Epoch = u64;
pub type Genesishash = Bytes;
pub type GenesisDelegateHash = Bytes;
pub type VrfKeyhash = Hash<32>;
/* move_instantaneous_reward = [ 0 / 1, { * stake_credential => delta_coin } / coin ]
; The first field determines where the funds are drawn from.
; 0 denotes the reserves, 1 denotes the treasury.
@ -298,7 +246,7 @@ impl<C> minicbor::encode::Encode<C> for InstantaneousRewardTarget {
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
#[cbor]
#[cbor()]
pub struct MoveInstantaneousReward {
#[n(0)]
pub source: InstantaneousRewardSource,
@ -307,180 +255,10 @@ pub struct MoveInstantaneousReward {
pub target: InstantaneousRewardTarget,
}
pub type RewardAccount = Bytes;
pub type Withdrawals = KeyValuePairs<RewardAccount, Coin>;
pub type RequiredSigners = Vec<AddrKeyhash>;
pub type Port = u32;
pub type IPv4 = Bytes;
pub type IPv6 = Bytes;
pub type DnsName = String;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Relay {
SingleHostAddr(Nullable<Port>, Nullable<IPv4>, Nullable<IPv6>),
SingleHostName(Nullable<Port>, DnsName),
MultiHostName(DnsName),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for Relay {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.array()?;
let variant = d.u16()?;
match variant {
0 => Ok(Relay::SingleHostAddr(
d.decode_with(ctx)?,
d.decode_with(ctx)?,
d.decode_with(ctx)?,
)),
1 => Ok(Relay::SingleHostName(
d.decode_with(ctx)?,
d.decode_with(ctx)?,
)),
2 => Ok(Relay::MultiHostName(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"invalid variant id for Relay",
)),
}
}
}
impl<C> minicbor::encode::Encode<C> for Relay {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Relay::SingleHostAddr(a, b, c) => {
e.array(4)?;
e.encode_with(0, ctx)?;
e.encode_with(a, ctx)?;
e.encode_with(b, ctx)?;
e.encode_with(c, ctx)?;
Ok(())
}
Relay::SingleHostName(a, b) => {
e.array(3)?;
e.encode_with(1, ctx)?;
e.encode_with(a, ctx)?;
e.encode_with(b, ctx)?;
Ok(())
}
Relay::MultiHostName(a) => {
e.array(2)?;
e.encode_with(2, ctx)?;
e.encode_with(a, ctx)?;
Ok(())
}
}
}
}
pub type PoolMetadataHash = Hash<32>;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct PoolMetadata {
#[n(0)]
pub url: String,
#[n(1)]
pub hash: PoolMetadataHash,
}
pub type AddrKeyhash = Hash<28>;
pub type Scripthash = Hash<28>;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct RationalNumber {
pub numerator: u64,
pub denominator: u64,
}
impl<'b, C> minicbor::decode::Decode<'b, C> for RationalNumber {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.tag()?;
d.array()?;
Ok(RationalNumber {
numerator: d.decode_with(ctx)?,
denominator: d.decode_with(ctx)?,
})
}
}
impl<C> minicbor::encode::Encode<C> for RationalNumber {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
// TODO: check if this is the correct tag
e.tag(Tag::Unassigned(30))?;
e.array(2)?;
e.encode_with(self.numerator, ctx)?;
e.encode_with(self.denominator, ctx)?;
Ok(())
}
}
pub type UnitInterval = RationalNumber;
pub type PositiveInterval = RationalNumber;
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Hash)]
pub enum StakeCredential {
AddrKeyhash(AddrKeyhash),
Scripthash(Scripthash),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for StakeCredential {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.array()?;
let variant = d.u16()?;
match variant {
0 => Ok(StakeCredential::AddrKeyhash(d.decode_with(ctx)?)),
1 => Ok(StakeCredential::Scripthash(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"invalid variant id for StakeCredential",
)),
}
}
}
impl<C> minicbor::encode::Encode<C> for StakeCredential {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
StakeCredential::AddrKeyhash(a) => {
e.array(2)?;
e.encode_with(0, ctx)?;
e.encode_with(a, ctx)?;
Ok(())
}
StakeCredential::Scripthash(a) => {
e.array(2)?;
e.encode_with(1, ctx)?;
e.encode_with(a, ctx)?;
Ok(())
}
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Certificate {
StakeRegistration(StakeCredential),
@ -649,17 +427,6 @@ impl<C> minicbor::encode::Encode<C> for Certificate {
}
}
#[derive(
Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy,
)]
#[cbor(index_only)]
pub enum NetworkId {
#[n(0)]
One,
#[n(1)]
Two,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
#[cbor(index_only)]
pub enum Language {
@ -667,9 +434,10 @@ pub enum Language {
PlutusV1,
}
pub type CostModel = Vec<i64>;
#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
pub type CostMdls = CostModels;
pub type CostMdls = KeyValuePairs<Language, CostModel>;
pub type CostModels = KeyValuePairs<Language, CostModel>;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(map)]
@ -709,7 +477,7 @@ pub struct ProtocolParamUpdate {
#[n(17)]
pub ada_per_utxo_byte: Option<Coin>,
#[n(18)]
pub cost_models_for_script_languages: Option<CostMdls>,
pub cost_models_for_script_languages: Option<CostModels>,
#[n(19)]
pub execution_costs: Option<ExUnitPrices>,
#[n(20)]
@ -862,380 +630,6 @@ impl<C> minicbor::encode::Encode<C> for NativeScript {
}
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(transparent)]
pub struct PlutusScript(#[n(0)] pub Bytes);
impl AsRef<[u8]> for PlutusScript {
fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}
/// Defined to encode PlutusData bytestring as it is done in the canonical
/// plutus implementation
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[serde(into = "String")]
#[serde(try_from = "String")]
pub struct BoundedBytes(Vec<u8>);
impl From<Vec<u8>> for BoundedBytes {
fn from(xs: Vec<u8>) -> Self {
BoundedBytes(xs)
}
}
impl From<BoundedBytes> for Vec<u8> {
fn from(b: BoundedBytes) -> Self {
b.0
}
}
impl Deref for BoundedBytes {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl TryFrom<String> for BoundedBytes {
type Error = hex::FromHexError;
fn try_from(value: String) -> Result<Self, Self::Error> {
let v = hex::decode(value)?;
Ok(BoundedBytes(v))
}
}
impl From<BoundedBytes> for String {
fn from(b: BoundedBytes) -> Self {
hex::encode(b.deref())
}
}
impl fmt::Display for BoundedBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bytes: Vec<u8> = self.clone().into();
f.write_str(&hex::encode(bytes))
}
}
impl<C> Encode<C> for BoundedBytes {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
_: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
// we match the haskell implementation by encoding bytestrings longer than 64
// bytes as indefinite lists of bytes
const CHUNK_SIZE: usize = 64;
let bs: &Vec<u8> = self.deref();
if bs.len() <= 64 {
e.bytes(bs)?;
} else {
e.begin_bytes()?;
for b in bs.chunks(CHUNK_SIZE) {
e.bytes(b)?;
}
e.end()?;
}
Ok(())
}
}
impl<'b, C> minicbor::decode::Decode<'b, C> for BoundedBytes {
fn decode(d: &mut minicbor::Decoder<'b>, _: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut res = Vec::new();
for chunk in d.bytes_iter()? {
let bs = chunk?;
res.extend_from_slice(bs);
}
Ok(BoundedBytes::from(res))
}
}
/*
big_int = int / big_uint / big_nint ; New
big_uint = #6.2(bounded_bytes) ; New
big_nint = #6.3(bounded_bytes) ; New
*/
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum BigInt {
Int(Int),
BigUInt(BoundedBytes),
BigNInt(BoundedBytes),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for BigInt {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let datatype = d.datatype()?;
match datatype {
minicbor::data::Type::U8
| minicbor::data::Type::U16
| minicbor::data::Type::U32
| minicbor::data::Type::U64
| minicbor::data::Type::I8
| minicbor::data::Type::I16
| minicbor::data::Type::I32
| minicbor::data::Type::I64
| minicbor::data::Type::Int => Ok(Self::Int(d.decode_with(ctx)?)),
minicbor::data::Type::Tag => {
let tag = d.tag()?;
match tag {
minicbor::data::Tag::PosBignum => Ok(Self::BigUInt(d.decode_with(ctx)?)),
minicbor::data::Tag::NegBignum => Ok(Self::BigNInt(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"invalid cbor tag for big int",
)),
}
}
_ => Err(minicbor::decode::Error::message(
"invalid cbor data type for big int",
)),
}
}
}
impl<C> minicbor::encode::Encode<C> for BigInt {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
BigInt::Int(x) => {
e.encode_with(x, ctx)?;
}
BigInt::BigUInt(x) => {
e.tag(Tag::PosBignum)?;
e.encode_with(x, ctx)?;
}
BigInt::BigNInt(x) => {
e.tag(Tag::NegBignum)?;
e.encode_with(x, ctx)?;
}
};
Ok(())
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum PlutusData {
Constr(Constr<PlutusData>),
Map(KeyValuePairs<PlutusData, PlutusData>),
BigInt(BigInt),
BoundedBytes(BoundedBytes),
Array(Vec<PlutusData>),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusData {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let type_ = d.datatype()?;
match type_ {
minicbor::data::Type::Tag => {
let mut probe = d.probe();
let tag = probe.tag()?;
match tag {
Tag::Unassigned(121..=127 | 1280..=1400 | 102) => {
Ok(Self::Constr(d.decode_with(ctx)?))
}
Tag::PosBignum | Tag::NegBignum => Ok(Self::BigInt(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"unknown tag for plutus data tag",
)),
}
}
minicbor::data::Type::U8
| minicbor::data::Type::U16
| minicbor::data::Type::U32
| minicbor::data::Type::U64
| minicbor::data::Type::I8
| minicbor::data::Type::I16
| minicbor::data::Type::I32
| minicbor::data::Type::I64
| minicbor::data::Type::Int => Ok(Self::BigInt(d.decode_with(ctx)?)),
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
Ok(Self::Map(d.decode_with(ctx)?))
}
minicbor::data::Type::Bytes => Ok(Self::BoundedBytes(d.decode_with(ctx)?)),
minicbor::data::Type::BytesIndef => {
let mut full = Vec::new();
for slice in d.bytes_iter()? {
full.extend(slice?);
}
Ok(Self::BoundedBytes(BoundedBytes::from(full)))
}
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
Ok(Self::Array(d.decode_with(ctx)?))
}
any => Err(minicbor::decode::Error::message(format!(
"bad cbor data type ({any:?}) for plutus data"
))),
}
}
}
fn encode_list<C, W: minicbor::encode::Write, A: minicbor::encode::Encode<C>>(
a: &Vec<A>,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
// Mimics default haskell list encoding from cborg:
// We use indef array for non-empty arrays but definite 0-length array for empty
if a.is_empty() {
e.array(0)?;
} else {
e.begin_array()?;
for v in a {
e.encode_with(v, ctx)?;
}
e.end()?;
}
Ok(())
}
impl<C> minicbor::encode::Encode<C> for PlutusData {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Self::Constr(a) => {
e.encode_with(a, ctx)?;
}
Self::Map(a) => {
// we use definite array to match the approach used by haskell's plutus
// implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
e.map(a.len().try_into().unwrap())?;
for (k, v) in a.iter() {
k.encode(e, ctx)?;
v.encode(e, ctx)?;
}
}
Self::BigInt(a) => {
e.encode_with(a, ctx)?;
}
Self::BoundedBytes(a) => {
e.encode_with(a, ctx)?;
}
Self::Array(a) => {
// we use definite array for empty array or indef array otherwise to match
// haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L153
// default encoder for a list:
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
encode_list(a, e, ctx)?;
}
};
Ok(())
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Constr<A> {
pub tag: u64,
pub any_constructor: Option<u64>,
pub fields: Vec<A>,
}
impl<'b, C, A> minicbor::decode::Decode<'b, C> for Constr<A>
where
A: minicbor::decode::Decode<'b, C>,
{
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let tag = d.tag()?;
match tag {
Tag::Unassigned(x) => match x {
121..=127 | 1280..=1400 => Ok(Constr {
tag: x,
fields: d.decode_with(ctx)?,
any_constructor: None,
}),
102 => {
d.array()?;
Ok(Constr {
tag: x,
any_constructor: Some(d.decode_with(ctx)?),
fields: d.decode_with(ctx)?,
})
}
_ => Err(minicbor::decode::Error::message(
"bad tag code for plutus data",
)),
},
_ => Err(minicbor::decode::Error::message(
"bad tag code for plutus data",
)),
}
}
}
impl<C, A> minicbor::encode::Encode<C> for Constr<A>
where
A: minicbor::encode::Encode<C>,
{
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(self.tag))?;
match self.tag {
102 => {
// definite length array here
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
e.array(2)?;
e.encode_with(self.any_constructor.unwrap_or_default(), ctx)?;
// we use definite array for empty array or indef array otherwise to match
// haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L144
// default encoder for a list:
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
encode_list(&self.fields, e, ctx)?;
Ok(())
}
_ => {
// we use definite array for empty array or indef array otherwise to match
// haskell implementation. See above reference.
encode_list(&self.fields, e, ctx)?;
Ok(())
}
}
}
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
pub struct ExUnits {
#[n(0)]
pub mem: u64,
#[n(1)]
pub steps: u64,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct ExUnitPrices {
#[n(0)]
pub mem_price: PositiveInterval,
#[n(1)]
pub step_price: PositiveInterval,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
#[cbor(index_only)]
pub enum RedeemerTag {
@ -1308,7 +702,7 @@ pub struct WitnessSet {
pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
#[n(3)]
pub plutus_script: Option<Vec<PlutusScript>>,
pub plutus_script: Option<Vec<PlutusScript<1>>>,
#[n(4)]
pub plutus_data: Option<Vec<PlutusData>>,
@ -1330,7 +724,7 @@ pub struct MintedWitnessSet<'b> {
pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
#[n(3)]
pub plutus_script: Option<Vec<PlutusScript>>,
pub plutus_script: Option<Vec<PlutusScript<1>>>,
#[b(4)]
pub plutus_data: Option<Vec<KeepRaw<'b, PlutusData>>>,
@ -1340,6 +734,7 @@ pub struct MintedWitnessSet<'b> {
}
impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
#[allow(deprecated)]
fn from(x: MintedWitnessSet<'b>) -> Self {
WitnessSet {
vkeywitness: x.vkeywitness,
@ -1366,80 +761,9 @@ pub struct PostAlonzoAuxiliaryData {
pub native_scripts: Option<Vec<NativeScript>>,
#[n(2)]
pub plutus_scripts: Option<Vec<PlutusScript>>,
pub plutus_scripts: Option<Vec<PlutusScript<1>>>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Metadatum {
Int(Int),
Bytes(Bytes),
Text(String),
Array(Vec<Metadatum>),
Map(KeyValuePairs<Metadatum, Metadatum>),
}
impl<'b, C> minicbor::Decode<'b, C> for Metadatum {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
match d.datatype()? {
minicbor::data::Type::U8
| minicbor::data::Type::U16
| minicbor::data::Type::U32
| minicbor::data::Type::U64
| minicbor::data::Type::I8
| minicbor::data::Type::I16
| minicbor::data::Type::I32
| minicbor::data::Type::I64
| minicbor::data::Type::Int => {
let i = d.decode()?;
Ok(Metadatum::Int(i))
}
minicbor::data::Type::Bytes => Ok(Metadatum::Bytes(d.decode_with(ctx)?)),
minicbor::data::Type::String => Ok(Metadatum::Text(d.decode_with(ctx)?)),
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
Ok(Metadatum::Array(d.decode_with(ctx)?))
}
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
Ok(Metadatum::Map(d.decode_with(ctx)?))
}
_ => Err(minicbor::decode::Error::message(
"Can't turn data type into metadatum",
)),
}
}
}
impl<C> minicbor::Encode<C> for Metadatum {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Metadatum::Int(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Bytes(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Text(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Array(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Map(a) => {
e.encode_with(a, ctx)?;
}
};
Ok(())
}
}
pub type MetadatumLabel = u64;
pub type Metadata = KeyValuePairs<MetadatumLabel, Metadatum>;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
pub struct ShelleyMaAuxiliaryData {
#[n(0)]
@ -1489,7 +813,7 @@ impl<C> minicbor::Encode<C> for AuxiliaryData {
}
AuxiliaryData::PostAlonzo(v) => {
// TODO: check if this is the correct tag
e.tag(Tag::Unassigned(259))?;
e.tag(Tag::new(259))?;
e.encode_with(v, ctx)?;
}
};
@ -1498,8 +822,6 @@ impl<C> minicbor::Encode<C> for AuxiliaryData {
}
}
pub type TransactionIndex = u32;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
pub struct Block {
#[n(0)]

View file

@ -4,15 +4,19 @@
use serde::{Deserialize, Serialize};
use pallas_codec::minicbor::{Decode, Encode};
use pallas_codec::{
minicbor::{self, Decode, Encode},
utils::{Bytes, CborWrap, KeepRaw, KeyValuePairs, MaybeIndefArray, Nullable},
};
use pallas_crypto::hash::{Hash, Hasher};
use pallas_codec::utils::{Bytes, CborWrap, KeepRaw, KeyValuePairs, MaybeIndefArray, Nullable};
// required for derive attrs to work
use pallas_codec::minicbor;
use crate::alonzo::VrfCert;
pub use crate::{
plutus_data::*, AddrKeyhash, AssetName, DatumHash, DnsName, Epoch, ExUnitPrices, ExUnits,
GenesisDelegateHash, Genesishash, IPv4, IPv6, Metadata, Metadatum, MetadatumLabel, NetworkId,
Nonce, NonceVariant, PlutusScript, PolicyId, PoolKeyhash, PoolMetadata, PoolMetadataHash, Port,
PositiveInterval, ProtocolVersion, RationalNumber, Relay, ScriptHash, StakeCredential,
TransactionIndex, TransactionInput, UnitInterval, VrfCert, VrfKeyhash,
};
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct HeaderBody {
@ -62,10 +66,6 @@ pub struct OperationalCert {
pub operational_cert_sigma: Bytes,
}
pub use crate::alonzo::ProtocolVersion;
pub use crate::alonzo::KesSignature;
pub type MintedHeaderBody<'a> = KeepRaw<'a, HeaderBody>;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
@ -97,18 +97,6 @@ impl<'a> From<MintedHeaderBody<'a>> for HeaderBody {
}
}
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;
@ -119,16 +107,6 @@ pub use crate::alonzo::Value;
pub use crate::alonzo::TransactionOutput as LegacyTransactionOutput;
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;
@ -137,40 +115,12 @@ pub use crate::alonzo::MoveInstantaneousReward;
pub use crate::alonzo::RewardAccount;
pub type Withdrawals = KeyValuePairs<RewardAccount, Coin>;
pub use crate::alonzo::Withdrawals;
pub type RequiredSigners = Vec<AddrKeyhash>;
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::RequiredSigners;
pub use crate::alonzo::Certificate;
pub use crate::alonzo::NetworkId;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(index_only)]
pub enum Language {
@ -181,11 +131,14 @@ pub enum Language {
PlutusV2,
}
#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
pub type CostMdls = CostModels;
pub use crate::alonzo::CostModel;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(map)]
pub struct CostMdls {
pub struct CostModels {
#[n(0)]
pub plutus_v1: Option<CostModel>,
@ -228,7 +181,7 @@ pub struct ProtocolParamUpdate {
#[n(17)]
pub ada_per_utxo_byte: Option<Coin>,
#[n(18)]
pub cost_models_for_script_languages: Option<CostMdls>,
pub cost_models_for_script_languages: Option<CostModels>,
#[n(19)]
pub execution_costs: Option<ExUnitPrices>,
#[n(20)]
@ -455,28 +408,6 @@ pub use crate::alonzo::VKeyWitness;
pub use crate::alonzo::NativeScript;
pub use crate::alonzo::PlutusScript as PlutusV1Script;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(transparent)]
pub struct PlutusV2Script(#[n(0)] pub Bytes);
impl AsRef<[u8]> for PlutusV2Script {
fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}
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;
@ -496,7 +427,7 @@ pub struct WitnessSet {
pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
#[n(3)]
pub plutus_v1_script: Option<Vec<PlutusV1Script>>,
pub plutus_v1_script: Option<Vec<PlutusScript<1>>>,
#[n(4)]
pub plutus_data: Option<Vec<PlutusData>>,
@ -505,7 +436,7 @@ pub struct WitnessSet {
pub redeemer: Option<Vec<Redeemer>>,
#[n(6)]
pub plutus_v2_script: Option<Vec<PlutusV2Script>>,
pub plutus_v2_script: Option<Vec<PlutusScript<2>>>,
}
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
@ -521,7 +452,7 @@ pub struct MintedWitnessSet<'b> {
pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
#[n(3)]
pub plutus_v1_script: Option<Vec<PlutusV1Script>>,
pub plutus_v1_script: Option<Vec<PlutusScript<1>>>,
#[b(4)]
pub plutus_data: Option<Vec<KeepRaw<'b, PlutusData>>>,
@ -530,7 +461,7 @@ pub struct MintedWitnessSet<'b> {
pub redeemer: Option<Vec<Redeemer>>,
#[n(6)]
pub plutus_v2_script: Option<Vec<PlutusV2Script>>,
pub plutus_v2_script: Option<Vec<PlutusScript<2>>>,
}
impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
@ -561,20 +492,16 @@ pub struct PostAlonzoAuxiliaryData {
pub native_scripts: Option<Vec<NativeScript>>,
#[n(2)]
pub plutus_v1_scripts: Option<Vec<PlutusV1Script>>,
pub plutus_v1_scripts: Option<Vec<PlutusScript<1>>>,
#[n(3)]
pub plutus_v2_scripts: Option<Vec<PlutusV2Script>>,
pub plutus_v2_scripts: Option<Vec<PlutusScript<2>>>,
}
pub type DatumHash = Hash<32>;
//pub type Data = CborWrap<PlutusData>;
// datum_option = [ 0, $hash32 // 1, data ]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PseudoDatumOption<T1> {
Hash(Hash<32>),
Hash(DatumHash),
Data(CborWrap<T1>),
}
@ -626,12 +553,18 @@ impl<'b> From<MintedDatumOption<'b>> for DatumOption {
}
}
#[deprecated(since = "0.31.0", note = "use `PlutusScript<1>` instead")]
pub type PlutusV1Script = PlutusScript<1>;
#[deprecated(since = "0.31.0", note = "use `PlutusScript<2>` instead")]
pub type PlutusV2Script = PlutusScript<2>;
// script = [ 0, native_script // 1, plutus_v1_script // 2, plutus_v2_script ]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PseudoScript<T1> {
NativeScript(T1),
PlutusV1Script(PlutusV1Script),
PlutusV2Script(PlutusV2Script),
PlutusV1Script(PlutusScript<1>),
PlutusV2Script(PlutusScript<2>),
}
// script_ref = #6.24(bytes .cbor script)
@ -689,16 +622,8 @@ where
}
}
pub use crate::alonzo::Metadatum;
pub use crate::alonzo::MetadatumLabel;
pub use crate::alonzo::Metadata;
pub use crate::alonzo::AuxiliaryData;
pub use crate::alonzo::TransactionIndex;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
pub struct PseudoBlock<T1, T2, T3, T4>
where

View file

@ -2,53 +2,34 @@
//!
//! Handcrafted, idiomatic rust artifacts based on based on the [Conway CDDL](https://github.com/IntersectMBO/cardano-ledger/blob/master/eras/conway/impl/cddl-files/conway.cddl) file in IntersectMBO repo.
use serde::{Deserialize, Serialize};
use std::ops::Deref;
use pallas_codec::minicbor::decode::Error;
use serde::{Deserialize, Serialize};
use pallas_codec::minicbor::{self, decode::Error, Decode, Encode};
use pallas_codec::utils::CborWrap;
use pallas_codec::minicbor::{Decode, Encode};
use pallas_crypto::hash::Hash;
use pallas_codec::utils::{
Bytes, CborWrap, KeepRaw, KeyValuePairs, MaybeIndefArray, NonEmptyKeyValuePairs, NonEmptySet,
NonZeroInt, Nullable, PositiveCoin, Set,
pub use crate::{
plutus_data::*, AddrKeyhash, AssetName, Bytes, Coin, CostModel, DnsName, Epoch, ExUnits,
GenesisDelegateHash, Genesishash, Hash, IPv4, IPv6, KeepRaw, KeyValuePairs, MaybeIndefArray,
Metadata, Metadatum, MetadatumLabel, NetworkId, NonEmptyKeyValuePairs, NonEmptySet, NonZeroInt,
Nonce, NonceVariant, Nullable, PlutusScript, PolicyId, PoolKeyhash, PoolMetadata,
PoolMetadataHash, Port, PositiveCoin, PositiveInterval, ProtocolVersion, RationalNumber, Relay,
RewardAccount, ScriptHash, Set, StakeCredential, TransactionIndex, TransactionInput,
UnitInterval, VrfCert, VrfKeyhash,
};
// required for derive attrs to work
use pallas_codec::minicbor;
pub use crate::alonzo::VrfCert;
use crate::babbage;
pub use crate::babbage::HeaderBody;
pub use crate::babbage::OperationalCert;
pub use crate::alonzo::ProtocolVersion;
pub use crate::alonzo::KesSignature;
pub use crate::babbage::Header;
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 type Multiasset<A> = NonEmptyKeyValuePairs<PolicyId, NonEmptyKeyValuePairs<AssetName, A>>;
pub type Mint = Multiasset<NonZeroInt>;
pub use crate::alonzo::Coin;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Value {
Coin(Coin),
@ -99,54 +80,10 @@ impl<C> minicbor::encode::Encode<C> for Value {
pub use crate::alonzo::TransactionOutput as LegacyTransactionOutput;
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 type Withdrawals = NonEmptyKeyValuePairs<RewardAccount, Coin>;
pub type RequiredSigners = NonEmptySet<AddrKeyhash>;
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;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Certificate {
StakeRegistration(StakeCredential),
@ -442,7 +379,7 @@ impl<C> minicbor::encode::Encode<C> for Certificate {
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
pub enum DRep {
Key(AddrKeyhash),
Script(Scripthash),
Script(ScriptHash),
Abstain,
NoConfidence,
}
@ -507,8 +444,6 @@ pub type CommitteeColdCredential = StakeCredential;
pub type CommitteeHotCredential = StakeCredential;
pub use crate::alonzo::NetworkId;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(index_only)]
pub enum Language {
@ -522,11 +457,12 @@ pub enum Language {
PlutusV3,
}
pub use crate::alonzo::CostModel;
#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
pub type CostMdls = CostModels;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(map)]
pub struct CostMdls {
pub struct CostModels {
#[n(0)]
pub plutus_v1: Option<CostModel>,
@ -570,7 +506,7 @@ pub struct ProtocolParamUpdate {
#[n(17)]
pub ada_per_utxo_byte: Option<Coin>,
#[n(18)]
pub cost_models_for_script_languages: Option<CostMdls>,
pub cost_models_for_script_languages: Option<CostModels>,
#[n(19)]
pub execution_costs: Option<ExUnitPrices>,
#[n(20)]
@ -1285,28 +1221,6 @@ pub use crate::alonzo::VKeyWitness;
pub use crate::alonzo::NativeScript;
pub use crate::alonzo::PlutusScript as PlutusV1Script;
pub use crate::babbage::PlutusV2Script;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(transparent)]
pub struct PlutusV3Script(#[n(0)] pub Bytes);
impl AsRef<[u8]> for PlutusV3Script {
fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}
pub use crate::alonzo::BigInt;
pub use crate::alonzo::PlutusData;
pub use crate::alonzo::Constr;
pub use crate::alonzo::ExUnits;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct ExUnitPrices {
#[n(0)]
@ -1446,7 +1360,7 @@ pub struct WitnessSet {
pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
#[n(3)]
pub plutus_v1_script: Option<NonEmptySet<PlutusV1Script>>,
pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
#[n(4)]
pub plutus_data: Option<NonEmptySet<PlutusData>>,
@ -1455,10 +1369,10 @@ pub struct WitnessSet {
pub redeemer: Option<Redeemers>,
#[n(6)]
pub plutus_v2_script: Option<NonEmptySet<PlutusV2Script>>,
pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
#[n(7)]
pub plutus_v3_script: Option<NonEmptySet<PlutusV3Script>>,
pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
}
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
@ -1474,7 +1388,7 @@ pub struct MintedWitnessSet<'b> {
pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
#[n(3)]
pub plutus_v1_script: Option<NonEmptySet<PlutusV1Script>>,
pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
#[b(4)]
pub plutus_data: Option<NonEmptySet<KeepRaw<'b, PlutusData>>>,
@ -1483,10 +1397,10 @@ pub struct MintedWitnessSet<'b> {
pub redeemer: Option<KeepRaw<'b, Redeemers>>,
#[n(6)]
pub plutus_v2_script: Option<NonEmptySet<PlutusV2Script>>,
pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
#[n(7)]
pub plutus_v3_script: Option<NonEmptySet<PlutusV3Script>>,
pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
}
impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
@ -1514,13 +1428,13 @@ pub struct PostAlonzoAuxiliaryData {
pub native_scripts: Option<Vec<NativeScript>>,
#[n(2)]
pub plutus_v1_scripts: Option<Vec<PlutusV1Script>>,
pub plutus_v1_scripts: Option<Vec<PlutusScript<1>>>,
#[n(3)]
pub plutus_v2_scripts: Option<Vec<PlutusV2Script>>,
pub plutus_v2_scripts: Option<Vec<PlutusScript<2>>>,
#[n(4)]
pub plutus_v3_scripts: Option<Vec<PlutusV3Script>>,
pub plutus_v3_scripts: Option<Vec<PlutusScript<3>>>,
}
pub use crate::babbage::DatumHash;
@ -1531,13 +1445,22 @@ pub use crate::babbage::DatumOption;
pub use crate::babbage::MintedDatumOption;
#[deprecated(since = "0.31.0", note = "use `PlutusScript<1>` instead")]
pub type PlutusV1Script = PlutusScript<1>;
#[deprecated(since = "0.31.0", note = "use `PlutusScript<2>` instead")]
pub type PlutusV2Script = PlutusScript<2>;
#[deprecated(since = "0.31.0", note = "use `PlutusScript<3>` instead")]
pub type PlutusV3Script = PlutusScript<3>;
// script = [ 0, native_script // 1, plutus_v1_script // 2, plutus_v2_script ]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PseudoScript<T1> {
NativeScript(T1),
PlutusV1Script(PlutusV1Script),
PlutusV2Script(PlutusV2Script),
PlutusV3Script(PlutusV3Script),
PlutusV1Script(PlutusScript<1>),
PlutusV2Script(PlutusScript<2>),
PlutusV3Script(PlutusScript<3>),
}
// script_ref = #6.24(bytes .cbor script)
@ -1610,15 +1533,8 @@ where
}
}
pub use crate::alonzo::Metadatum;
pub use crate::alonzo::MetadatumLabel;
pub use crate::alonzo::Metadata;
pub use crate::alonzo::AuxiliaryData;
pub use crate::alonzo::TransactionIndex;
use crate::babbage::MintedHeader;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]

View file

@ -1,10 +1,402 @@
//! Ledger primitives and cbor codec for the Cardano eras
mod framework;
mod plutus_data;
pub mod alonzo;
pub mod babbage;
pub mod byron;
pub mod conway;
pub use plutus_data::*;
pub use framework::*;
pub use pallas_codec::utils::{
Bytes, Int, KeepRaw, KeyValuePairs, MaybeIndefArray, NonEmptyKeyValuePairs, NonEmptySet,
NonZeroInt, Nullable, PositiveCoin, Set,
};
pub use pallas_crypto::hash::Hash;
use pallas_codec::minicbor::{self, data::Tag, Decode, Encode};
use serde::{Deserialize, Serialize};
// ----- Common type definitions
pub type AddrKeyhash = Hash<28>;
pub type AssetName = Bytes;
pub type Coin = u64;
pub type CostModel = Vec<i64>;
pub type DatumHash = Hash<32>;
pub type DnsName = String;
pub type Epoch = u64;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
pub struct ExUnits {
#[n(0)]
pub mem: u64,
#[n(1)]
pub steps: u64,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct ExUnitPrices {
#[n(0)]
pub mem_price: PositiveInterval,
#[n(1)]
pub step_price: PositiveInterval,
}
pub type Genesishash = Bytes;
pub type GenesisDelegateHash = Bytes;
pub type IPv4 = Bytes;
pub type IPv6 = Bytes;
pub type Metadata = KeyValuePairs<MetadatumLabel, Metadatum>;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Metadatum {
Int(Int),
Bytes(Bytes),
Text(String),
Array(Vec<Metadatum>),
Map(KeyValuePairs<Metadatum, Metadatum>),
}
impl<'b, C> minicbor::Decode<'b, C> for Metadatum {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
match d.datatype()? {
minicbor::data::Type::U8
| minicbor::data::Type::U16
| minicbor::data::Type::U32
| minicbor::data::Type::U64
| minicbor::data::Type::I8
| minicbor::data::Type::I16
| minicbor::data::Type::I32
| minicbor::data::Type::I64
| minicbor::data::Type::Int => {
let i = d.decode()?;
Ok(Metadatum::Int(i))
}
minicbor::data::Type::Bytes => Ok(Metadatum::Bytes(d.decode_with(ctx)?)),
minicbor::data::Type::String => Ok(Metadatum::Text(d.decode_with(ctx)?)),
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
Ok(Metadatum::Array(d.decode_with(ctx)?))
}
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
Ok(Metadatum::Map(d.decode_with(ctx)?))
}
_ => Err(minicbor::decode::Error::message(
"Can't turn data type into metadatum",
)),
}
}
}
impl<C> minicbor::Encode<C> for Metadatum {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Metadatum::Int(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Bytes(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Text(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Array(a) => {
e.encode_with(a, ctx)?;
}
Metadatum::Map(a) => {
e.encode_with(a, ctx)?;
}
};
Ok(())
}
}
pub type MetadatumLabel = u64;
#[derive(
Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy,
)]
#[cbor(index_only)]
pub enum NetworkId {
#[n(0)]
Testnet,
#[n(1)]
Mainnet,
}
impl From<NetworkId> for u8 {
fn from(network_id: NetworkId) -> u8 {
match network_id {
NetworkId::Testnet => 0,
NetworkId::Mainnet => 1,
}
}
}
impl TryFrom<u8> for NetworkId {
type Error = ();
fn try_from(i: u8) -> Result<Self, Self::Error> {
match i {
0 => Ok(Self::Testnet),
1 => Ok(Self::Mainnet),
_ => Err(()),
}
}
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct Nonce {
#[n(0)]
pub variant: NonceVariant,
#[n(1)]
pub hash: Option<Hash<32>>,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(index_only)]
pub enum NonceVariant {
#[n(0)]
NeutralNonce,
#[n(1)]
Nonce,
}
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(transparent)]
pub struct PlutusScript<const VERSION: usize>(#[n(0)] pub Bytes);
impl<const VERSION: usize> AsRef<[u8]> for PlutusScript<VERSION> {
fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}
pub type PolicyId = Hash<28>;
pub type PoolKeyhash = Hash<28>;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct PoolMetadata {
#[n(0)]
pub url: String,
#[n(1)]
pub hash: PoolMetadataHash,
}
pub type PoolMetadataHash = Hash<32>;
pub type Port = u32;
pub type PositiveInterval = RationalNumber;
pub type ProtocolVersion = (u64, u64);
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct RationalNumber {
pub numerator: u64,
pub denominator: u64,
}
impl<'b, C> minicbor::decode::Decode<'b, C> for RationalNumber {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
// TODO: Enforce tag == 30 & array of size 2
d.tag()?;
d.array()?;
Ok(RationalNumber {
numerator: d.decode_with(ctx)?,
denominator: d.decode_with(ctx)?,
})
}
}
impl<C> minicbor::encode::Encode<C> for RationalNumber {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::new(30))?;
e.array(2)?;
e.encode_with(self.numerator, ctx)?;
e.encode_with(self.denominator, ctx)?;
Ok(())
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Relay {
SingleHostAddr(Nullable<Port>, Nullable<IPv4>, Nullable<IPv6>),
SingleHostName(Nullable<Port>, DnsName),
MultiHostName(DnsName),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for Relay {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.array()?;
let variant = d.u16()?;
match variant {
0 => Ok(Relay::SingleHostAddr(
d.decode_with(ctx)?,
d.decode_with(ctx)?,
d.decode_with(ctx)?,
)),
1 => Ok(Relay::SingleHostName(
d.decode_with(ctx)?,
d.decode_with(ctx)?,
)),
2 => Ok(Relay::MultiHostName(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"invalid variant id for Relay",
)),
}
}
}
impl<C> minicbor::encode::Encode<C> for Relay {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Relay::SingleHostAddr(a, b, c) => {
e.array(4)?;
e.encode_with(0, ctx)?;
e.encode_with(a, ctx)?;
e.encode_with(b, ctx)?;
e.encode_with(c, ctx)?;
Ok(())
}
Relay::SingleHostName(a, b) => {
e.array(3)?;
e.encode_with(1, ctx)?;
e.encode_with(a, ctx)?;
e.encode_with(b, ctx)?;
Ok(())
}
Relay::MultiHostName(a) => {
e.array(2)?;
e.encode_with(2, ctx)?;
e.encode_with(a, ctx)?;
Ok(())
}
}
}
}
pub type RewardAccount = Bytes;
pub type ScriptHash = Hash<28>;
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Hash)]
// !! NOTE / IMPORTANT !!
// It is tempting to swap the order of the two constructors so that AddrKeyHash
// comes first. This indeed nicely maps the binary representation which
// associates 0 to AddrKeyHash and 1 to ScriptHash.
//
// However, for historical reasons, the ScriptHash variant comes first in the
// Haskell reference codebase. From this ordering is derived the `PartialOrd`
// and `Ord` instances; which impacts how Maps/Dictionnaries indexed by
// StakeCredential will be ordered. So, it is crucial to preserve this quirks to
// avoid hard to troubleshoot issues down the line.
pub enum StakeCredential {
ScriptHash(ScriptHash),
AddrKeyhash(AddrKeyhash),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for StakeCredential {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.array()?;
let variant = d.u16()?;
match variant {
0 => Ok(StakeCredential::AddrKeyhash(d.decode_with(ctx)?)),
1 => Ok(StakeCredential::ScriptHash(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"invalid variant id for StakeCredential",
)),
}
}
}
impl<C> minicbor::encode::Encode<C> for StakeCredential {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
StakeCredential::AddrKeyhash(a) => {
e.array(2)?;
e.encode_with(0, ctx)?;
e.encode_with(a, ctx)?;
Ok(())
}
StakeCredential::ScriptHash(a) => {
e.array(2)?;
e.encode_with(1, ctx)?;
e.encode_with(a, ctx)?;
Ok(())
}
}
}
}
pub type TransactionIndex = u32;
#[derive(
Serialize,
Deserialize,
Encode,
Decode,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
std::hash::Hash,
)]
pub struct TransactionInput {
#[n(0)]
pub transaction_id: Hash<32>,
#[n(1)]
pub index: u64,
}
pub type UnitInterval = RationalNumber;
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
pub struct VrfCert(#[n(0)] pub Bytes, #[n(1)] pub Bytes);
pub type VrfKeyhash = Hash<32>;

View file

@ -0,0 +1,353 @@
use crate::KeyValuePairs;
use pallas_codec::minicbor::{
self,
data::{IanaTag, Tag},
Encode,
};
use pallas_codec::utils::Int;
use serde::{Deserialize, Serialize};
use std::{fmt, ops::Deref};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum PlutusData {
Constr(Constr<PlutusData>),
Map(KeyValuePairs<PlutusData, PlutusData>),
BigInt(BigInt),
BoundedBytes(BoundedBytes),
Array(Vec<PlutusData>),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusData {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let type_ = d.datatype()?;
match type_ {
minicbor::data::Type::Tag => {
let mut probe = d.probe();
let tag = probe.tag()?;
if tag == IanaTag::PosBignum.tag() || tag == IanaTag::NegBignum.tag() {
Ok(Self::BigInt(d.decode_with(ctx)?))
} else {
match tag.as_u64() {
(121..=127) | (1280..=1400) | 102 => Ok(Self::Constr(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"unknown tag for plutus data tag",
)),
}
}
}
minicbor::data::Type::U8
| minicbor::data::Type::U16
| minicbor::data::Type::U32
| minicbor::data::Type::U64
| minicbor::data::Type::I8
| minicbor::data::Type::I16
| minicbor::data::Type::I32
| minicbor::data::Type::I64
| minicbor::data::Type::Int => Ok(Self::BigInt(d.decode_with(ctx)?)),
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
Ok(Self::Map(d.decode_with(ctx)?))
}
minicbor::data::Type::Bytes => Ok(Self::BoundedBytes(d.decode_with(ctx)?)),
minicbor::data::Type::BytesIndef => {
let mut full = Vec::new();
for slice in d.bytes_iter()? {
full.extend(slice?);
}
Ok(Self::BoundedBytes(BoundedBytes::from(full)))
}
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
Ok(Self::Array(d.decode_with(ctx)?))
}
any => Err(minicbor::decode::Error::message(format!(
"bad cbor data type ({any:?}) for plutus data"
))),
}
}
}
impl<C> minicbor::encode::Encode<C> for PlutusData {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Self::Constr(a) => {
e.encode_with(a, ctx)?;
}
Self::Map(a) => {
// we use definite array to match the approach used by haskell's plutus
// implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
e.map(a.len().try_into().unwrap())?;
for (k, v) in a.iter() {
k.encode(e, ctx)?;
v.encode(e, ctx)?;
}
}
Self::BigInt(a) => {
e.encode_with(a, ctx)?;
}
Self::BoundedBytes(a) => {
e.encode_with(a, ctx)?;
}
Self::Array(a) => {
// we use definite array for empty array or indef array otherwise to match
// haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L153
// default encoder for a list:
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
encode_list(a, e, ctx)?;
}
};
Ok(())
}
}
/*
big_int = int / big_uint / big_nint ; New
big_uint = #6.2(bounded_bytes) ; New
big_nint = #6.3(bounded_bytes) ; New
*/
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum BigInt {
Int(Int),
BigUInt(BoundedBytes),
BigNInt(BoundedBytes),
}
impl<'b, C> minicbor::decode::Decode<'b, C> for BigInt {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let datatype = d.datatype()?;
match datatype {
minicbor::data::Type::U8
| minicbor::data::Type::U16
| minicbor::data::Type::U32
| minicbor::data::Type::U64
| minicbor::data::Type::I8
| minicbor::data::Type::I16
| minicbor::data::Type::I32
| minicbor::data::Type::I64
| minicbor::data::Type::Int => Ok(Self::Int(d.decode_with(ctx)?)),
minicbor::data::Type::Tag => {
let tag = d.tag()?;
if tag == IanaTag::PosBignum.tag() {
Ok(Self::BigUInt(d.decode_with(ctx)?))
} else if tag == IanaTag::NegBignum.tag() {
Ok(Self::BigNInt(d.decode_with(ctx)?))
} else {
Err(minicbor::decode::Error::message(
"invalid cbor tag for big int",
))
}
}
_ => Err(minicbor::decode::Error::message(
"invalid cbor data type for big int",
)),
}
}
}
impl<C> minicbor::encode::Encode<C> for BigInt {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
BigInt::Int(x) => {
e.encode_with(x, ctx)?;
}
BigInt::BigUInt(x) => {
e.tag(IanaTag::PosBignum)?;
e.encode_with(x, ctx)?;
}
BigInt::BigNInt(x) => {
e.tag(IanaTag::NegBignum)?;
e.encode_with(x, ctx)?;
}
};
Ok(())
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Constr<A> {
pub tag: u64,
pub any_constructor: Option<u64>,
pub fields: Vec<A>,
}
impl<'b, C, A> minicbor::decode::Decode<'b, C> for Constr<A>
where
A: minicbor::decode::Decode<'b, C>,
{
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let tag = d.tag()?;
let x = tag.as_u64();
match x {
121..=127 | 1280..=1400 => Ok(Constr {
tag: x,
fields: d.decode_with(ctx)?,
any_constructor: None,
}),
102 => {
d.array()?;
Ok(Constr {
tag: x,
any_constructor: Some(d.decode_with(ctx)?),
fields: d.decode_with(ctx)?,
})
}
_ => Err(minicbor::decode::Error::message(
"bad tag code for plutus data",
)),
}
}
}
impl<C, A> minicbor::encode::Encode<C> for Constr<A>
where
A: minicbor::encode::Encode<C>,
{
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::new(self.tag))?;
match self.tag {
102 => {
// definite length array here
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
e.array(2)?;
e.encode_with(self.any_constructor.unwrap_or_default(), ctx)?;
// we use definite array for empty array or indef array otherwise to match
// haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L144
// default encoder for a list:
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
encode_list(&self.fields, e, ctx)?;
Ok(())
}
_ => {
// we use definite array for empty array or indef array otherwise to match
// haskell implementation. See above reference.
encode_list(&self.fields, e, ctx)?;
Ok(())
}
}
}
}
/// Defined to encode PlutusData bytestring as it is done in the canonical
/// plutus implementation
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[serde(into = "String")]
#[serde(try_from = "String")]
pub struct BoundedBytes(Vec<u8>);
impl From<Vec<u8>> for BoundedBytes {
fn from(xs: Vec<u8>) -> Self {
BoundedBytes(xs)
}
}
impl From<BoundedBytes> for Vec<u8> {
fn from(b: BoundedBytes) -> Self {
b.0
}
}
impl Deref for BoundedBytes {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl TryFrom<String> for BoundedBytes {
type Error = hex::FromHexError;
fn try_from(value: String) -> Result<Self, Self::Error> {
let v = hex::decode(value)?;
Ok(BoundedBytes(v))
}
}
impl From<BoundedBytes> for String {
fn from(b: BoundedBytes) -> Self {
hex::encode(b.deref())
}
}
impl fmt::Display for BoundedBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bytes: Vec<u8> = self.clone().into();
f.write_str(&hex::encode(bytes))
}
}
impl<C> Encode<C> for BoundedBytes {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
_: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
// we match the haskell implementation by encoding bytestrings longer than 64
// bytes as indefinite lists of bytes
const CHUNK_SIZE: usize = 64;
let bs: &Vec<u8> = self.deref();
if bs.len() <= 64 {
e.bytes(bs)?;
} else {
e.begin_bytes()?;
for b in bs.chunks(CHUNK_SIZE) {
e.bytes(b)?;
}
e.end()?;
}
Ok(())
}
}
impl<'b, C> minicbor::decode::Decode<'b, C> for BoundedBytes {
fn decode(d: &mut minicbor::Decoder<'b>, _: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut res = Vec::new();
for chunk in d.bytes_iter()? {
let bs = chunk?;
res.extend_from_slice(bs);
}
Ok(BoundedBytes::from(res))
}
}
fn encode_list<C, W: minicbor::encode::Write, A: minicbor::encode::Encode<C>>(
a: &Vec<A>,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
// Mimics default haskell list encoding from cborg:
// We use indef array for non-empty arrays but definite 0-length array for empty
if a.is_empty() {
e.array(0)?;
} else {
e.begin_array()?;
for v in a {
e.encode_with(v, ctx)?;
}
e.end()?;
}
Ok(())
}

View file

@ -5,7 +5,7 @@ use pallas_primitives::alonzo;
use crate::MultiEraTx;
impl<'b> MultiEraTx<'b> {
pub fn aux_plutus_v1_scripts(&self) -> &[alonzo::PlutusScript] {
pub fn aux_plutus_v1_scripts(&self) -> &[alonzo::PlutusScript<1>] {
if let Some(aux_data) = self.aux_data() {
if let alonzo::AuxiliaryData::PostAlonzo(x) = aux_data.deref() {
if let Some(plutus) = &x.plutus_scripts {

View file

@ -82,9 +82,9 @@ impl OriginalHash<28> for KeepRaw<'_, alonzo::NativeScript> {
}
}
impl ComputeHash<28> for alonzo::PlutusScript {
impl<const VERSION: usize> ComputeHash<28> for alonzo::PlutusScript<VERSION> {
fn compute_hash(&self) -> Hash<28> {
Hasher::<224>::hash_tagged(&self.0, 1)
Hasher::<224>::hash_tagged(&self.0, VERSION as u8)
}
}
@ -124,12 +124,6 @@ impl OriginalHash<32> for KeepRaw<'_, babbage::Header> {
}
}
impl ComputeHash<28> for babbage::PlutusV2Script {
fn compute_hash(&self) -> Hash<28> {
Hasher::<224>::hash_tagged(&self.0, 2)
}
}
impl ComputeHash<32> for babbage::TransactionBody {
fn compute_hash(&self) -> Hash<32> {
Hasher::<256>::hash_cbor(self)
@ -159,12 +153,6 @@ impl ComputeHash<32> for babbage::DatumOption {
// conway
impl ComputeHash<28> for conway::PlutusV3Script {
fn compute_hash(&self) -> Hash<28> {
Hasher::<224>::hash_tagged(&self.0, 3)
}
}
impl ComputeHash<32> for conway::TransactionBody {
fn compute_hash(&self) -> Hash<32> {
Hasher::<256>::hash_cbor(self)
@ -334,7 +322,7 @@ mod tests {
fn plutus_v1_script_hashes_as_cardano_cli() {
let bytecode_hex = include_str!("../../test_data/jpgstore.plutus");
let bytecode = hex::decode(bytecode_hex).unwrap();
let script = alonzo::PlutusScript(Bytes::from(bytecode));
let script = alonzo::PlutusScript::<1>(Bytes::from(bytecode));
let generated = script.compute_hash().to_string();
@ -350,7 +338,7 @@ mod tests {
fn plutus_v2_script_hashes_as_cardano_cli() {
let bytecode_hex = include_str!("../../test_data/v2script.plutus");
let bytecode = hex::decode(bytecode_hex).unwrap();
let script = babbage::PlutusV2Script(Bytes::from(bytecode));
let script = babbage::PlutusScript::<2>(Bytes::from(bytecode));
let generated = script.compute_hash().to_string();

View file

@ -1,6 +1,6 @@
//! Lightweight inspection of block data without full CBOR decoding
use pallas_codec::minicbor::decode::{Token, Tokenizer};
use pallas_codec::minicbor::{data::Token, decode::Tokenizer};
use crate::Era;

View file

@ -47,9 +47,9 @@ pub type UnitInterval = alonzo::UnitInterval;
pub type Nonce = alonzo::Nonce;
pub type ExUnitPrices = alonzo::ExUnitPrices;
pub type ExUnits = alonzo::ExUnits;
pub type AlonzoCostMdls = alonzo::CostMdls;
pub type BabbageCostMdls = babbage::CostMdls;
pub type ConwayCostMdls = conway::CostMdls;
pub type AlonzoCostModels = alonzo::CostModels;
pub type BabbageCostModels = babbage::CostModels;
pub type ConwayCostModels = conway::CostModels;
pub type ProtocolVersion = alonzo::ProtocolVersion;
pub type PoolVotingThresholds = conway::PoolVotingThresholds;
pub type DRepVotingThresholds = conway::DRepVotingThresholds;
@ -157,7 +157,9 @@ impl<'b> MultiEraUpdate<'b> {
}
}
pub fn alonzo_first_proposed_cost_models_for_script_languages(&self) -> Option<AlonzoCostMdls> {
pub fn alonzo_first_proposed_cost_models_for_script_languages(
&self,
) -> Option<AlonzoCostModels> {
match self {
MultiEraUpdate::AlonzoCompatible(x) => x
.proposed_protocol_parameter_updates
@ -169,7 +171,7 @@ impl<'b> MultiEraUpdate<'b> {
pub fn babbage_first_proposed_cost_models_for_script_languages(
&self,
) -> Option<BabbageCostMdls> {
) -> Option<BabbageCostModels> {
match self {
MultiEraUpdate::Babbage(x) => x
.proposed_protocol_parameter_updates
@ -179,7 +181,9 @@ impl<'b> MultiEraUpdate<'b> {
}
}
pub fn conway_first_proposed_cost_models_for_script_languages(&self) -> Option<ConwayCostMdls> {
pub fn conway_first_proposed_cost_models_for_script_languages(
&self,
) -> Option<ConwayCostModels> {
match self {
MultiEraUpdate::Conway(x) => x
.proposed_protocol_parameter_updates

View file

@ -1,8 +1,7 @@
use pallas_codec::utils::KeepRaw;
use pallas_primitives::{
alonzo::{self, BootstrapWitness, NativeScript, PlutusData, VKeyWitness},
babbage::PlutusV2Script,
conway::PlutusV3Script,
alonzo::{self, BootstrapWitness, NativeScript, VKeyWitness},
PlutusData, PlutusScript,
};
use crate::{MultiEraRedeemer, MultiEraTx};
@ -80,7 +79,7 @@ impl<'b> MultiEraTx<'b> {
}
}
pub fn plutus_v1_scripts(&self) -> &[alonzo::PlutusScript] {
pub fn plutus_v1_scripts(&self) -> &[alonzo::PlutusScript<1>] {
match self {
Self::Byron(_) => &[],
Self::AlonzoCompatible(x, _) => x
@ -181,7 +180,7 @@ impl<'b> MultiEraTx<'b> {
})
}
pub fn plutus_v2_scripts(&self) -> &[PlutusV2Script] {
pub fn plutus_v2_scripts(&self) -> &[PlutusScript<2>] {
match self {
Self::Byron(_) => &[],
Self::AlonzoCompatible(_, _) => &[],
@ -200,7 +199,7 @@ impl<'b> MultiEraTx<'b> {
}
}
pub fn plutus_v3_scripts(&self) -> &[PlutusV3Script] {
pub fn plutus_v3_scripts(&self) -> &[PlutusScript<3>] {
match self {
Self::Byron(_) => &[],
Self::AlonzoCompatible(_, _) => &[],

View file

@ -4,10 +4,10 @@ use pallas_codec::utils::{CborWrap, KeyValuePairs};
use pallas_crypto::hash::Hash;
use pallas_primitives::{
babbage::{
DatumOption, ExUnits as PallasExUnits, NativeScript, NetworkId, PlutusData, PlutusV1Script,
PlutusV2Script, PostAlonzoTransactionOutput, PseudoScript as PallasScript,
PseudoTransactionOutput, Redeemer, RedeemerTag, TransactionBody, TransactionInput,
Tx as BabbageTx, Value, WitnessSet,
DatumOption, ExUnits as PallasExUnits, NativeScript, NetworkId, PlutusData, PlutusScript,
PostAlonzoTransactionOutput, PseudoScript as PallasScript, PseudoTransactionOutput,
Redeemer, RedeemerTag, TransactionBody, TransactionInput, Tx as BabbageTx, Value,
WitnessSet,
},
Fragment,
};
@ -88,10 +88,9 @@ impl BuildBabbage for StagingTransaction {
.collect();
let network_id = if let Some(nid) = self.network_id {
match nid {
0 => Some(NetworkId::One),
1 => Some(NetworkId::Two),
_ => return Err(TxBuilderError::InvalidNetworkId),
match NetworkId::try_from(nid) {
Err(()) => return Err(TxBuilderError::InvalidNetworkId),
Ok(network_id) => Some(network_id),
}
} else {
None
@ -125,12 +124,12 @@ impl BuildBabbage for StagingTransaction {
native_script.push(script)
}
ScriptKind::PlutusV1 => {
let script = PlutusV1Script(script.bytes.into());
let script = PlutusScript::<1>(script.bytes.into());
plutus_v1_script.push(script)
}
ScriptKind::PlutusV2 => {
let script = PlutusV2Script(script.bytes.into());
let script = PlutusScript::<2>(script.bytes.into());
plutus_v2_script.push(script)
}
@ -313,12 +312,12 @@ impl Output {
NativeScript::decode_fragment(s.bytes.as_ref())
.map_err(|_| TxBuilderError::MalformedScript)?,
),
ScriptKind::PlutusV1 => {
PallasScript::PlutusV1Script(PlutusV1Script(s.bytes.as_ref().to_vec().into()))
}
ScriptKind::PlutusV2 => {
PallasScript::PlutusV2Script(PlutusV2Script(s.bytes.as_ref().to_vec().into()))
}
ScriptKind::PlutusV1 => PallasScript::PlutusV1Script(PlutusScript::<1>(
s.bytes.as_ref().to_vec().into(),
)),
ScriptKind::PlutusV2 => PallasScript::PlutusV2Script(PlutusScript::<2>(
s.bytes.as_ref().to_vec().into(),
)),
};
Some(CborWrap(script))

View file

@ -185,7 +185,7 @@ impl<C: LedgerContext> Mapper<C> {
babbage::StakeCredential::AddrKeyhash(x) => {
u5c::stake_credential::StakeCredential::AddrKeyHash(x.to_vec().into())
}
babbage::StakeCredential::Scripthash(x) => {
babbage::StakeCredential::ScriptHash(x) => {
u5c::stake_credential::StakeCredential::ScriptHash(x.to_vec().into())
}
};