From 90939dbf37bce429f86e520e65df8f2524beeaf3 Mon Sep 17 00:00:00 2001 From: jmhrpr Date: Tue, 2 Jan 2024 19:30:40 +0000 Subject: [PATCH 1/2] fix: update pallas-applying to work with keepraw native scripts --- pallas-applying/src/shelley_ma.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pallas-applying/src/shelley_ma.rs b/pallas-applying/src/shelley_ma.rs index b05930a3..9b7e5b84 100644 --- a/pallas-applying/src/shelley_ma.rs +++ b/pallas-applying/src/shelley_ma.rs @@ -21,7 +21,7 @@ use pallas_primitives::{ byron::TxOut, }; use pallas_traverse::{ComputeHash, Era, MultiEraInput, MultiEraOutput}; -use std::collections::HashMap; +use std::{collections::HashMap, ops::Deref}; // TODO: implement each of the validation rules. pub fn validate_shelley_ma_tx( @@ -38,7 +38,11 @@ pub fn validate_shelley_ma_tx( let auxiliary_data_hash: &Option = &tx_body.auxiliary_data_hash; let auxiliary_data: &Option<&[u8]> = &extract_auxiliary_data(mtx); let minted_value: &Option> = &tx_body.mint; - let native_script_wits: &Option> = &mtx.transaction_witness_set.native_script; + let native_script_wits: &Option> = &mtx + .transaction_witness_set + .native_script + .as_ref() + .map(|x| x.iter().map(|y| y.deref().clone()).collect()); check_ins_not_empty(tx_body)?; check_ins_in_utxos(tx_body, utxos)?; check_ttl(tx_body, block_slot)?; @@ -397,9 +401,13 @@ fn check_witnesses( ShelleyPaymentPart::Key(payment_key_hash) => { check_verification_key_witness(&payment_key_hash, tx_hash, wits)? } - ShelleyPaymentPart::Script(script_hash) => { - check_native_script_witness(&script_hash, &tx_wits.native_script)? - } + ShelleyPaymentPart::Script(script_hash) => check_native_script_witness( + &script_hash, + &tx_wits + .native_script + .as_ref() + .map(|x| x.iter().map(|y| y.deref().clone()).collect()), + )?, } } } From ae7663ce96eeed45e52dc41c8585bb6e94ffe3e4 Mon Sep 17 00:00:00 2001 From: jmhrpr Date: Wed, 3 Jan 2024 23:01:48 +0000 Subject: [PATCH 2/2] feat: tx builder metadata simple, with era-specific aux data fixes --- pallas-primitives/src/babbage/model.rs | 52 ++++++- pallas-primitives/src/conway/model.rs | 52 ++++++- pallas-traverse/src/auxiliary.rs | 134 +++++++++++++++--- pallas-traverse/src/hashes.rs | 12 ++ pallas-traverse/src/tx.rs | 93 +++++++----- pallas-txbuilder/src/babbage.rs | 67 +++++++-- pallas-txbuilder/src/lib.rs | 7 +- pallas-txbuilder/src/transaction/model.rs | 43 +++++- pallas-txbuilder/src/transaction/serialise.rs | 1 + 9 files changed, 390 insertions(+), 71 deletions(-) diff --git a/pallas-primitives/src/babbage/model.rs b/pallas-primitives/src/babbage/model.rs index 72d673db..bb933365 100644 --- a/pallas-primitives/src/babbage/model.rs +++ b/pallas-primitives/src/babbage/model.rs @@ -2,6 +2,7 @@ //! //! 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::data::Tag; use serde::{Deserialize, Serialize}; use pallas_codec::minicbor::{Decode, Encode}; @@ -644,7 +645,56 @@ pub use crate::alonzo::MetadatumLabel; pub use crate::alonzo::Metadata; -pub use crate::alonzo::AuxiliaryData; +use crate::alonzo::ShelleyMaAuxiliaryData; + +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub enum AuxiliaryData { + Shelley(Metadata), + ShelleyMa(ShelleyMaAuxiliaryData), + PostAlonzo(PostAlonzoAuxiliaryData), +} + +impl<'b, C> minicbor::Decode<'b, C> for AuxiliaryData { + fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result { + match d.datatype()? { + minicbor::data::Type::Map | minicbor::data::Type::MapIndef => { + Ok(AuxiliaryData::Shelley(d.decode_with(ctx)?)) + } + minicbor::data::Type::Array => Ok(AuxiliaryData::ShelleyMa(d.decode_with(ctx)?)), + minicbor::data::Type::Tag => { + d.tag()?; + Ok(AuxiliaryData::PostAlonzo(d.decode_with(ctx)?)) + } + _ => Err(minicbor::decode::Error::message( + "Can't infer variant from data type for AuxiliaryData", + )), + } + } +} + +impl minicbor::Encode for AuxiliaryData { + fn encode( + &self, + e: &mut minicbor::Encoder, + ctx: &mut C, + ) -> Result<(), minicbor::encode::Error> { + match self { + AuxiliaryData::Shelley(m) => { + e.encode_with(m, ctx)?; + } + AuxiliaryData::ShelleyMa(m) => { + e.encode_with(m, ctx)?; + } + AuxiliaryData::PostAlonzo(v) => { + // TODO: check if this is the correct tag + e.tag(Tag::Unassigned(259))?; + e.encode_with(v, ctx)?; + } + }; + + Ok(()) + } +} pub use crate::alonzo::TransactionIndex; diff --git a/pallas-primitives/src/conway/model.rs b/pallas-primitives/src/conway/model.rs index 61b30b97..45345a92 100644 --- a/pallas-primitives/src/conway/model.rs +++ b/pallas-primitives/src/conway/model.rs @@ -2,6 +2,7 @@ //! //! Handcrafted, idiomatic rust artifacts based on based on the [Conway CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/conway/test-suite/cddl-files/conway.cddl) file in IOHK repo. +use pallas_codec::minicbor::data::Tag; use serde::{Deserialize, Serialize}; use pallas_codec::minicbor::{Decode, Encode}; @@ -1400,7 +1401,56 @@ pub use crate::alonzo::MetadatumLabel; pub use crate::alonzo::Metadata; -pub use crate::alonzo::AuxiliaryData; +use crate::alonzo::ShelleyMaAuxiliaryData; + +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub enum AuxiliaryData { + Shelley(Metadata), + ShelleyMa(ShelleyMaAuxiliaryData), + PostAlonzo(PostAlonzoAuxiliaryData), +} + +impl<'b, C> minicbor::Decode<'b, C> for AuxiliaryData { + fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result { + match d.datatype()? { + minicbor::data::Type::Map | minicbor::data::Type::MapIndef => { + Ok(AuxiliaryData::Shelley(d.decode_with(ctx)?)) + } + minicbor::data::Type::Array => Ok(AuxiliaryData::ShelleyMa(d.decode_with(ctx)?)), + minicbor::data::Type::Tag => { + d.tag()?; + Ok(AuxiliaryData::PostAlonzo(d.decode_with(ctx)?)) + } + _ => Err(minicbor::decode::Error::message( + "Can't infer variant from data type for AuxiliaryData", + )), + } + } +} + +impl minicbor::Encode for AuxiliaryData { + fn encode( + &self, + e: &mut minicbor::Encoder, + ctx: &mut C, + ) -> Result<(), minicbor::encode::Error> { + match self { + AuxiliaryData::Shelley(m) => { + e.encode_with(m, ctx)?; + } + AuxiliaryData::ShelleyMa(m) => { + e.encode_with(m, ctx)?; + } + AuxiliaryData::PostAlonzo(v) => { + // TODO: check if this is the correct tag + e.tag(Tag::Unassigned(259))?; + e.encode_with(v, ctx)?; + } + }; + + Ok(()) + } +} pub use crate::alonzo::TransactionIndex; diff --git a/pallas-traverse/src/auxiliary.rs b/pallas-traverse/src/auxiliary.rs index 3df55992..1c126bd0 100644 --- a/pallas-traverse/src/auxiliary.rs +++ b/pallas-traverse/src/auxiliary.rs @@ -1,39 +1,137 @@ use std::ops::Deref; -use pallas_primitives::alonzo; +use pallas_codec::utils::Nullable; +use pallas_primitives::{alonzo, babbage, conway}; use crate::MultiEraTx; impl<'b> MultiEraTx<'b> { pub fn aux_plutus_v1_scripts(&self) -> &[alonzo::PlutusScript] { - if let Some(aux_data) = self.aux_data() { - if let alonzo::AuxiliaryData::PostAlonzo(x) = aux_data.deref() { - if let Some(plutus) = &x.plutus_scripts { - return plutus.as_ref(); + match self { + MultiEraTx::Byron(_) => &[], + MultiEraTx::AlonzoCompatible(x, _) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + alonzo::AuxiliaryData::PostAlonzo(y) => { + if let Some(scripts) = y.plutus_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + _ => &[], + } + } else { + &[] + } + } + MultiEraTx::Babbage(x) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + babbage::AuxiliaryData::PostAlonzo(y) => { + if let Some(scripts) = y.plutus_v1_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + _ => &[], + } + } else { + &[] + } + } + MultiEraTx::Conway(x) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + conway::AuxiliaryData::PostAlonzo(y) => { + if let Some(scripts) = y.plutus_v1_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + _ => &[], + } + } else { + &[] } } } - - &[] } pub fn aux_native_scripts(&self) -> &[alonzo::NativeScript] { - if let Some(aux_data) = self.aux_data() { - match aux_data.deref() { - alonzo::AuxiliaryData::PostAlonzo(x) => { - if let Some(scripts) = &x.native_scripts { - return scripts.as_ref(); + match self { + MultiEraTx::Byron(_) => &[], + MultiEraTx::AlonzoCompatible(x, _) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + alonzo::AuxiliaryData::ShelleyMa(y) => { + if let Some(scripts) = y.auxiliary_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + alonzo::AuxiliaryData::PostAlonzo(y) => { + if let Some(scripts) = y.native_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + _ => &[], + } + } else { + &[] + } + } + MultiEraTx::Babbage(x) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + babbage::AuxiliaryData::ShelleyMa(y) => { + if let Some(scripts) = y.auxiliary_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + babbage::AuxiliaryData::PostAlonzo(y) => { + if let Some(scripts) = y.native_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + _ => &[], } + } else { + &[] } - alonzo::AuxiliaryData::ShelleyMa(x) => { - if let Some(scripts) = &x.auxiliary_scripts { - return scripts.as_ref(); + } + MultiEraTx::Conway(x) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + conway::AuxiliaryData::ShelleyMa(y) => { + if let Some(scripts) = y.auxiliary_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + conway::AuxiliaryData::PostAlonzo(y) => { + if let Some(scripts) = y.native_scripts.as_ref() { + scripts.as_ref() + } else { + &[] + } + } + _ => &[], } + } else { + &[] } - _ => (), } } - - &[] } } diff --git a/pallas-traverse/src/hashes.rs b/pallas-traverse/src/hashes.rs index ee2f62dd..2a28da0d 100644 --- a/pallas-traverse/src/hashes.rs +++ b/pallas-traverse/src/hashes.rs @@ -151,6 +151,12 @@ impl ComputeHash<32> for babbage::DatumOption { } } +impl ComputeHash<32> for babbage::AuxiliaryData { + fn compute_hash(&self) -> pallas_crypto::hash::Hash<32> { + Hasher::<256>::hash_cbor(self) + } +} + // conway impl ComputeHash<28> for conway::PlutusV3Script { @@ -177,6 +183,12 @@ impl OriginalHash<32> for KeepRaw<'_, conway::MintedTransactionBody<'_>> { } } +impl ComputeHash<32> for conway::AuxiliaryData { + fn compute_hash(&self) -> pallas_crypto::hash::Hash<32> { + Hasher::<256>::hash_cbor(self) + } +} + impl ComputeHash<28> for PublicKey { fn compute_hash(&self) -> Hash<28> { Hasher::<224>::hash(&Into::<[u8; PublicKey::SIZE]>::into(*self)) diff --git a/pallas-traverse/src/tx.rs b/pallas-traverse/src/tx.rs index 3506ecb6..316b5c1d 100644 --- a/pallas-traverse/src/tx.rs +++ b/pallas-traverse/src/tx.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, collections::HashSet, ops::Deref}; -use pallas_codec::{minicbor, utils::KeepRaw}; +use pallas_codec::{minicbor, utils::Nullable}; use pallas_crypto::hash::Hash; use pallas_primitives::{ alonzo, @@ -457,41 +457,66 @@ impl<'b> MultiEraTx<'b> { } } - pub(crate) fn aux_data(&self) -> Option<&KeepRaw<'_, alonzo::AuxiliaryData>> { - match self { - MultiEraTx::AlonzoCompatible(x, _) => match &x.auxiliary_data { - pallas_codec::utils::Nullable::Some(x) => Some(x), - pallas_codec::utils::Nullable::Null => None, - pallas_codec::utils::Nullable::Undefined => None, - }, - MultiEraTx::Babbage(x) => match &x.auxiliary_data { - pallas_codec::utils::Nullable::Some(x) => Some(x), - pallas_codec::utils::Nullable::Null => None, - pallas_codec::utils::Nullable::Undefined => None, - }, - MultiEraTx::Byron(_) => None, - MultiEraTx::Conway(x) => match &x.auxiliary_data { - pallas_codec::utils::Nullable::Some(x) => Some(x), - pallas_codec::utils::Nullable::Null => None, - pallas_codec::utils::Nullable::Undefined => None, - }, - } - } - pub fn metadata(&self) -> MultiEraMeta { - match self.aux_data() { - Some(x) => match x.deref() { - alonzo::AuxiliaryData::Shelley(x) => MultiEraMeta::AlonzoCompatible(x), - alonzo::AuxiliaryData::ShelleyMa(x) => { - MultiEraMeta::AlonzoCompatible(&x.transaction_metadata) + match self { + MultiEraTx::Byron(_) => MultiEraMeta::NotApplicable, + MultiEraTx::AlonzoCompatible(x, _) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + alonzo::AuxiliaryData::Shelley(y) => MultiEraMeta::AlonzoCompatible(y), + alonzo::AuxiliaryData::ShelleyMa(y) => { + MultiEraMeta::AlonzoCompatible(&y.transaction_metadata) + } + alonzo::AuxiliaryData::PostAlonzo(y) => { + if let Some(z) = &y.metadata { + MultiEraMeta::AlonzoCompatible(z) + } else { + MultiEraMeta::Empty + } + } + } + } else { + MultiEraMeta::Empty } - alonzo::AuxiliaryData::PostAlonzo(x) => x - .metadata - .as_ref() - .map(MultiEraMeta::AlonzoCompatible) - .unwrap_or_default(), - }, - None => MultiEraMeta::Empty, + } + MultiEraTx::Babbage(x) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + babbage::AuxiliaryData::Shelley(y) => MultiEraMeta::AlonzoCompatible(y), + babbage::AuxiliaryData::ShelleyMa(y) => { + MultiEraMeta::AlonzoCompatible(&y.transaction_metadata) + } + babbage::AuxiliaryData::PostAlonzo(y) => { + if let Some(z) = &y.metadata { + MultiEraMeta::AlonzoCompatible(z) + } else { + MultiEraMeta::Empty + } + } + } + } else { + MultiEraMeta::Empty + } + } + MultiEraTx::Conway(x) => { + if let Nullable::Some(ad) = &x.auxiliary_data { + match ad.deref() { + conway::AuxiliaryData::Shelley(y) => MultiEraMeta::AlonzoCompatible(y), + conway::AuxiliaryData::ShelleyMa(y) => { + MultiEraMeta::AlonzoCompatible(&y.transaction_metadata) + } + conway::AuxiliaryData::PostAlonzo(y) => { + if let Some(z) = &y.metadata { + MultiEraMeta::AlonzoCompatible(z) + } else { + MultiEraMeta::Empty + } + } + } + } else { + MultiEraMeta::Empty + } + } } } diff --git a/pallas-txbuilder/src/babbage.rs b/pallas-txbuilder/src/babbage.rs index 7acc9bc1..d18ca161 100644 --- a/pallas-txbuilder/src/babbage.rs +++ b/pallas-txbuilder/src/babbage.rs @@ -4,10 +4,11 @@ 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, + AuxiliaryData, DatumOption, ExUnits as PallasExUnits, Metadatum as PallasMetadatum, + NativeScript, NetworkId, PlutusData, PlutusV1Script, PlutusV2Script, + PostAlonzoTransactionOutput, PseudoScript as PallasScript, PseudoTransactionOutput, + Redeemer, RedeemerTag, TransactionBody, TransactionInput, Tx as BabbageTx, Value, + WitnessSet, }, Fragment, }; @@ -16,8 +17,8 @@ use pallas_traverse::ComputeHash; use crate::{ transaction::{ model::{ - BuilderEra, BuiltTransaction, DatumKind, ExUnits, Output, RedeemerPurpose, ScriptKind, - StagingTransaction, + BuilderEra, BuiltTransaction, DatumKind, ExUnits, Metadatum, Output, RedeemerPurpose, + ScriptKind, StagingTransaction, }, opt_if_empty, Bytes, Bytes32, TransactionStatus, }, @@ -206,6 +207,20 @@ impl BuildBabbage for StagingTransaction { } }; + let metadata = match self.metadata { + Some(x) => { + let mut out = vec![]; + for (label, md) in x.0.into_iter() { + let new_md = metadatum_conversion(md)?; + out.push((label, new_md)) + } + Some(out.into()) + } + None => None, + }; + + let auxiliary_data = metadata.map(AuxiliaryData::Shelley); + let mut pallas_tx = BabbageTx { transaction_body: TransactionBody { inputs, @@ -213,10 +228,10 @@ impl BuildBabbage for StagingTransaction { ttl: self.invalid_from_slot, validity_interval_start: self.valid_from_slot, fee: self.fee.unwrap_or_default(), - certificates: None, // TODO - withdrawals: None, // TODO - update: None, // TODO - auxiliary_data_hash: None, // TODO (accept user input) + certificates: None, // TODO + withdrawals: None, // TODO + update: None, // TODO + auxiliary_data_hash: None, mint, script_data_hash: self.script_data_hash.map(|x| x.0.into()), collateral: opt_if_empty(collateral), @@ -235,11 +250,10 @@ impl BuildBabbage for StagingTransaction { plutus_data: opt_if_empty(plutus_data), redeemer: opt_if_empty(redeemers), }, - success: true, // TODO - auxiliary_data: None.into(), // TODO + auxiliary_data: auxiliary_data.into(), + success: true, // TODO }; - // TODO: pallas auxiliary_data_hash should be Hash<32> not Bytes pallas_tx.transaction_body.auxiliary_data_hash = pallas_tx .auxiliary_data .clone() @@ -261,6 +275,33 @@ impl BuildBabbage for StagingTransaction { // } } +fn metadatum_conversion(metadatum: Metadatum) -> Result { + match metadatum { + Metadatum::Int(x) => Ok(PallasMetadatum::Int( + x.try_into().map_err(|_| TxBuilderError::IntOutOfBounds)?, + )), + Metadatum::Text(x) => Ok(PallasMetadatum::Text(x)), + Metadatum::Array(x) => Ok(PallasMetadatum::Array( + x.into_iter() + .map(|y| metadatum_conversion(y)) + .collect::, _>>()?, + )), + Metadatum::Bytes(x) => Ok(PallasMetadatum::Bytes(x.into())), + Metadatum::Map(x) => { + let mut out = vec![]; + + for (k, v) in x.into_iter() { + let new_k = metadatum_conversion(k)?; + let new_v = metadatum_conversion(v)?; + + out.push((new_k, new_v)) + } + + Ok(PallasMetadatum::Map(out.into())) + } + } +} + fn babbage_output( output: &Output, ) -> Result, TxBuilderError> { diff --git a/pallas-txbuilder/src/lib.rs b/pallas-txbuilder/src/lib.rs index 7ecdafe8..163bfb0f 100644 --- a/pallas-txbuilder/src/lib.rs +++ b/pallas-txbuilder/src/lib.rs @@ -2,7 +2,9 @@ mod babbage; mod transaction; pub use babbage::BuildBabbage; -pub use transaction::model::{BuiltTransaction, Input, Output, ScriptKind, StagingTransaction}; +pub use transaction::model::{ + BuiltTransaction, Input, Metadatum, Output, ScriptKind, StagingTransaction, +}; #[derive(Debug, Clone, PartialEq, thiserror::Error)] pub enum TxBuilderError { @@ -31,4 +33,7 @@ pub enum TxBuilderError { /// Asset name is too long, it must be 32 bytes or less #[error("Asset name must be 32 bytes or less")] AssetNameTooLong, + /// Metadata/PlutusData integer must be in range [-2^64, 2^64 - 1] + #[error("Metadata/PlutusData integer must be in range [-2^64, 2^64 - 1]")] + IntOutOfBounds, } diff --git a/pallas-txbuilder/src/transaction/model.rs b/pallas-txbuilder/src/transaction/model.rs index 52c83870..950ef7b1 100644 --- a/pallas-txbuilder/src/transaction/model.rs +++ b/pallas-txbuilder/src/transaction/model.rs @@ -36,13 +36,13 @@ pub struct StagingTransaction { pub scripts: Option>, pub datums: Option>, pub redeemers: Option, - pub script_data_hash: Option, pub signature_amount_override: Option, pub change_address: Option
, + pub metadata: Option, + pub script_data_hash: Option, // pub certificates: TODO // pub withdrawals: TODO // pub updates: TODO - // pub auxiliary_data: TODO // pub phase_2_valid: TODO } @@ -370,6 +370,26 @@ impl StagingTransaction { self.change_address = None; self } + + pub fn set_metadata_label(mut self, label: u64, metadatum: Metadatum) -> Self { + let mut metadata = self.metadata.map(|x| x.0).unwrap_or_default(); + + metadata.insert(label, metadatum); + + self.metadata = Some(Metadata(metadata)); + + self + } + + pub fn remove_metadata_label(mut self, label: u64) -> Self { + let mut metadata = self.metadata.map(|x| x.0).unwrap_or_default(); + + metadata.remove(&label); + + self.metadata = Some(Metadata(metadata)); + + self + } } // TODO: Don't want our wrapper types in fields public @@ -592,6 +612,19 @@ impl From for Address { } } +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] +pub struct Metadata(pub HashMap); + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum Metadatum { + Int(i128), + Bytes(Vec), + Text(String), + Array(Vec), + Map(Vec<(Metadatum, Metadatum)>), +} + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] #[serde(rename_all = "snake_case")] pub enum BuilderEra { @@ -616,7 +649,11 @@ impl BuiltTransaction { .try_into() .map_err(|_| TxBuilderError::MalformedKey)?; - let signature: [u8; ed25519::Signature::SIZE] = private_key.sign(self.tx_hash.0).as_ref().try_into().unwrap(); + let signature: [u8; ed25519::Signature::SIZE] = private_key + .sign(self.tx_hash.0) + .as_ref() + .try_into() + .unwrap(); match self.era { BuilderEra::Babbage => { diff --git a/pallas-txbuilder/src/transaction/serialise.rs b/pallas-txbuilder/src/transaction/serialise.rs index 5dd9bccf..52fd8c05 100644 --- a/pallas-txbuilder/src/transaction/serialise.rs +++ b/pallas-txbuilder/src/transaction/serialise.rs @@ -479,6 +479,7 @@ mod tests { signature_amount_override: Some(5), change_address: Some(Address(PallasAddress::from_str("addr1g9ekml92qyvzrjmawxkh64r2w5xr6mg9ngfmxh2khsmdrcudevsft64mf887333adamant").unwrap())), script_data_hash: Some(Bytes32([0; 32])), + metadata: None, }; let serialised_tx = serde_json::to_string(&tx).unwrap();