Skip to content

Commit

Permalink
move to conway
Browse files Browse the repository at this point in the history
  • Loading branch information
scarmuega committed Oct 23, 2024
1 parent 074b277 commit 122eafe
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 106 deletions.
16 changes: 16 additions & 0 deletions pallas-codec/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ where
pub fn to_vec(self) -> Vec<(K, V)> {
self.into()
}

pub fn from_vec(x: Vec<(K, V)>) -> Option<Self> {
if x.is_empty() {
None
} else {
Some(NonEmptyKeyValuePairs::Def(x))
}
}
}

impl<K, V> From<NonEmptyKeyValuePairs<K, V>> for Vec<(K, V)>
Expand Down Expand Up @@ -777,6 +785,14 @@ impl<T> NonEmptySet<T> {
pub fn to_vec(self) -> Vec<T> {
self.0
}

pub fn from_vec(x: Vec<T>) -> Option<Self> {
if x.is_empty() {
None
} else {
Some(Self(x))
}
}
}

impl<T> Deref for NonEmptySet<T> {
Expand Down
2 changes: 1 addition & 1 deletion pallas-traverse/src/redeemers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl<'b> MultiEraRedeemer<'b> {
Self::AlonzoCompatible(Box::new(Cow::Borrowed(redeemer)))
}

pub fn from_conway_map(
pub fn from_conway(
redeemers_key: &'b conway::RedeemersKey,
redeemers_val: &'b conway::RedeemersValue,
) -> Self {
Expand Down
184 changes: 104 additions & 80 deletions pallas-txbuilder/src/babbage.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::ops::Deref;

use pallas_codec::utils::{CborWrap, KeyValuePairs};
use pallas_codec::utils::CborWrap;
use pallas_crypto::hash::Hash;
use pallas_primitives::{
babbage::{
DatumOption, ExUnits as PallasExUnits, NativeScript, NetworkId, PlutusData, PlutusScript,
PostAlonzoTransactionOutput, PseudoScript as PallasScript, PseudoTransactionOutput,
Redeemer, RedeemerTag, TransactionBody, TransactionInput, Tx as BabbageTx, Value,
WitnessSet,
conway::{
DatumOption, ExUnits as PallasExUnits, NativeScript, NetworkId, NonZeroInt, PlutusData,
PlutusScript, PostAlonzoTransactionOutput, PseudoScript as PallasScript,
PseudoTransactionOutput, Redeemer, RedeemerTag, TransactionBody, TransactionInput,
Tx as BabbageTx, Value, WitnessSet,
},
Fragment,
Fragment, NonEmptyKeyValuePairs, NonEmptySet, PositiveCoin,
};
use pallas_traverse::ComputeHash;

Expand All @@ -20,7 +20,7 @@ use crate::{
BuilderEra, BuiltTransaction, DatumKind, ExUnits, Output, RedeemerPurpose, ScriptKind,
StagingTransaction,
},
opt_if_empty, Bytes, Bytes32, TransactionStatus,
Bytes, Bytes32, TransactionStatus,
},
TxBuilderError,
};
Expand Down Expand Up @@ -53,40 +53,43 @@ impl BuildBabbage for StagingTransaction {
.map(Output::build_babbage_raw)
.collect::<Result<Vec<_>, _>>()?;

let mint: Option<KeyValuePairs<Hash<28>, KeyValuePairs<_, _>>> = self.mint.map(|massets| {
massets
.deref()
let mint = NonEmptyKeyValuePairs::from_vec(
self.mint
.iter()
.flat_map(|x| x.deref().iter())
.map(|(pid, assets)| {
(
pid.0.into(),
assets
.iter()
.map(|(n, x)| (n.clone().into(), *x))
.collect::<Vec<_>>()
.into(),
Hash::<28>::from(pid.0),
NonEmptyKeyValuePairs::from_vec(
assets
.iter()
.map(|(n, x)| (n.clone().into(), NonZeroInt::try_from(*x).unwrap()))
.collect::<Vec<_>>(),
)
.unwrap(),
)
})
.collect::<Vec<_>>()
.into()
});
.collect::<Vec<_>>(),
);

let collateral = self
.collateral_inputs
.unwrap_or_default()
.iter()
.map(|x| TransactionInput {
transaction_id: x.tx_hash.0.into(),
index: x.txo_index,
})
.collect();
let collateral = NonEmptySet::from_vec(
self.collateral_inputs
.unwrap_or_default()
.iter()
.map(|x| TransactionInput {
transaction_id: x.tx_hash.0.into(),
index: x.txo_index,
})
.collect(),
);

let required_signers = self
.disclosed_signers
.unwrap_or_default()
.iter()
.map(|x| x.0.into())
.collect();
let required_signers = NonEmptySet::from_vec(
self.disclosed_signers
.unwrap_or_default()
.iter()
.map(|x| x.0.into())
.collect(),
);

let network_id = if let Some(nid) = self.network_id {
match NetworkId::try_from(nid) {
Expand All @@ -103,18 +106,19 @@ impl BuildBabbage for StagingTransaction {
.map(Output::build_babbage_raw)
.transpose()?;

let reference_inputs = self
.reference_inputs
.unwrap_or_default()
.iter()
.map(|x| TransactionInput {
transaction_id: x.tx_hash.0.into(),
index: x.txo_index,
})
.collect();
let reference_inputs = NonEmptySet::from_vec(
self.reference_inputs
.unwrap_or_default()
.iter()
.map(|x| TransactionInput {
transaction_id: x.tx_hash.0.into(),
index: x.txo_index,
})
.collect(),
);

let (mut native_script, mut plutus_v1_script, mut plutus_v2_script) =
(vec![], vec![], vec![]);
let (mut native_script, mut plutus_v1_script, mut plutus_v2_script, mut plutus_v3_script) =
(vec![], vec![], vec![], vec![]);

for (_, script) in self.scripts.unwrap_or_default() {
match script.kind {
Expand All @@ -134,6 +138,11 @@ impl BuildBabbage for StagingTransaction {

plutus_v2_script.push(script)
}
ScriptKind::PlutusV3 => {
let script = PlutusScript::<3>(script.bytes.into());

plutus_v3_script.push(script)
}
}
}

Expand All @@ -148,10 +157,9 @@ impl BuildBabbage for StagingTransaction {
.collect::<Result<Vec<_>, _>>()?;

let mut mint_policies = mint
.clone()
.unwrap_or(vec![].into())
.iter()
.map(|(p, _)| **p)
.flat_map(|x| x.deref().iter())
.map(|(p, _)| *p)
.collect::<Vec<_>>();

mint_policies.sort_unstable_by_key(|x| *x);
Expand Down Expand Up @@ -192,7 +200,7 @@ impl BuildBabbage for StagingTransaction {
RedeemerPurpose::Mint(pid) => {
let index = mint_policies
.iter()
.position(|x| *x == pid.0)
.position(|x| x.as_slice() == pid.0)
.ok_or(TxBuilderError::RedeemerTargetMissing)?
as u32;

Expand All @@ -207,43 +215,55 @@ impl BuildBabbage for StagingTransaction {
}
};

let script_data_hash = scriptdata::ScriptData {
redeemers: pallas_primitives::conway::Redeemers::List(
pallas_codec::utils::MaybeIndefArray::Def(redeemers.clone()),
),
datums: Some(plutus_data),
language_view: self.language_view,
}
.hash();
let witness_set_redeemers = pallas_primitives::conway::Redeemers::List(
pallas_codec::utils::MaybeIndefArray::Def(redeemers.clone()),
);

let script_data_hash = if let Some(language_view) = self.language_view {
Some(
scriptdata::ScriptData {
redeemers: witness_set_redeemers.clone(),
datums: Some(plutus_data.clone()),
language_view,
}
.hash(),
)
} else {
None
};

let mut pallas_tx = BabbageTx {
transaction_body: TransactionBody {
inputs,
inputs: pallas_primitives::Set::from(inputs),
outputs,
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)
mint,
script_data_hash: Some(script_data_hash),
collateral: opt_if_empty(collateral),
required_signers: opt_if_empty(required_signers),
script_data_hash,
collateral,
required_signers,
network_id,
collateral_return,
total_collateral: None, // TODO
reference_inputs: opt_if_empty(reference_inputs),
reference_inputs,
total_collateral: None, // TODO
voting_procedures: None, // TODO
proposal_procedures: None, // TODO
treasury_value: None, // TODO
donation: None, // TODO
},
transaction_witness_set: WitnessSet {
vkeywitness: None,
native_script: opt_if_empty(native_script),
native_script: NonEmptySet::from_vec(native_script),
bootstrap_witness: None,
plutus_v1_script: opt_if_empty(plutus_v1_script),
plutus_v2_script: opt_if_empty(plutus_v2_script),
plutus_data: opt_if_empty(plutus_data),
redeemer: opt_if_empty(redeemers),
plutus_v1_script: NonEmptySet::from_vec(plutus_v1_script),
plutus_v2_script: NonEmptySet::from_vec(plutus_v2_script),
plutus_v3_script: NonEmptySet::from_vec(plutus_v3_script),
plutus_data: NonEmptySet::from_vec(plutus_data),
redeemer: Some(witness_set_redeemers),
},
success: true, // TODO
auxiliary_data: None.into(), // TODO
Expand Down Expand Up @@ -275,26 +295,27 @@ impl Output {
pub fn build_babbage_raw(
&self,
) -> Result<PseudoTransactionOutput<PostAlonzoTransactionOutput>, TxBuilderError> {
let value = if let Some(ref assets) = self.assets {
let txb_assets = assets
.deref()
let assets = NonEmptyKeyValuePairs::from_vec(
self.assets
.iter()
.flat_map(|x| x.deref().iter())
.map(|(pid, assets)| {
(
pid.0.into(),
assets
.iter()
.map(|(n, x)| (n.clone().into(), *x))
.map(|(n, x)| (n.clone().into(), PositiveCoin::try_from(*x).unwrap()))
.collect::<Vec<_>>()
.into(),
.try_into()
.unwrap(),
)
})
.collect::<Vec<_>>()
.into();
.collect::<Vec<_>>(),
);

Value::Multiasset(self.lovelace, txb_assets)
} else {
Value::Coin(self.lovelace)
let value = match assets {
Some(assets) => Value::Multiasset(self.lovelace, assets),
None => Value::Coin(self.lovelace),
};

let datum_option = if let Some(ref d) = self.datum {
Expand Down Expand Up @@ -329,6 +350,9 @@ impl Output {
ScriptKind::PlutusV2 => PallasScript::PlutusV2Script(PlutusScript::<2>(
s.bytes.as_ref().to_vec().into(),
)),
ScriptKind::PlutusV3 => PallasScript::PlutusV3Script(PlutusScript::<3>(
s.bytes.as_ref().to_vec().into(),
)),
};

Some(CborWrap(script))
Expand Down
11 changes: 4 additions & 7 deletions pallas-txbuilder/src/scriptdata.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use pallas_codec::{
minicbor::{self, Encode},
utils::{KeyValuePairs, NonEmptySet},
};

use pallas_codec::minicbor::{self, Encode};
use pallas_primitives::conway::{CostModel, PlutusData, Redeemers};
use serde::{Deserialize, Serialize};

pub type PlutusVersion = u8;

#[derive(Debug, Clone)]
pub struct LanguageView(PlutusVersion, CostModel);
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct LanguageView(pub PlutusVersion, pub CostModel);

impl<C> Encode<C> for LanguageView {
fn encode<W: minicbor::encode::Write>(
Expand Down
11 changes: 1 addition & 10 deletions pallas-txbuilder/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct Bytes64(pub [u8; 64]);
type PublicKey = Bytes32;
type Signature = Bytes64;

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub struct Hash28(pub [u8; 28]);

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
Expand Down Expand Up @@ -52,12 +52,3 @@ pub type PolicyId = ScriptHash;
pub type DatumHash = Bytes32;
pub type DatumBytes = Bytes;
pub type AssetName = Bytes;

/// If a Vec is empty, returns None, or Some(Vec) if not empty
pub fn opt_if_empty<T>(v: Vec<T>) -> Option<Vec<T>> {
if v.is_empty() {
None
} else {
Some(v)
}
}
Loading

0 comments on commit 122eafe

Please sign in to comment.