From e79925414219c66c4750acfd48cd75b4c43583c3 Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Wed, 24 Sep 2025 16:46:37 -0300 Subject: [PATCH 1/7] serialization as an adhoc directive and datum compilation of function --- crates/tx3-cardano/src/compile/mod.rs | 15 +-- crates/tx3-cardano/src/compile/plutus_data.rs | 23 +++- crates/tx3-lang/src/cardano.rs | 114 ++++++++++++++++++ crates/tx3-lang/src/tx3.pest | 7 +- examples/cardano_witness.mint_from_plutus.tir | 6 +- examples/reference_script.publish_native.tir | 26 ++-- examples/reference_script.publish_plutus.tir | 22 ++-- 7 files changed, 169 insertions(+), 44 deletions(-) diff --git a/crates/tx3-cardano/src/compile/mod.rs b/crates/tx3-cardano/src/compile/mod.rs index 72edb08a..5467c404 100644 --- a/crates/tx3-cardano/src/compile/mod.rs +++ b/crates/tx3-cardano/src/compile/mod.rs @@ -73,20 +73,7 @@ fn compile_struct(ir: &ir::StructExpr) -> Result } fn compile_data_expr(ir: &ir::Expression) -> Result { - match ir { - ir::Expression::Bytes(x) => Ok(x.as_data()), - ir::Expression::Number(x) => Ok(x.as_data()), - ir::Expression::Bool(x) => Ok(x.as_data()), - ir::Expression::String(x) => Ok(x.as_str().as_data()), - ir::Expression::Struct(x) => compile_struct(x), - ir::Expression::Map(x) => x.try_as_data(), - ir::Expression::Address(x) => Ok(x.as_data()), - ir::Expression::List(x) => x.try_as_data(), - _ => Err(Error::CoerceError( - format!("{ir:?}"), - "DataExpr".to_string(), - )), - } + ir.try_as_data() } fn compile_native_asset_for_output( diff --git a/crates/tx3-cardano/src/compile/plutus_data.rs b/crates/tx3-cardano/src/compile/plutus_data.rs index 3d67b479..854b9c0d 100644 --- a/crates/tx3-cardano/src/compile/plutus_data.rs +++ b/crates/tx3-cardano/src/compile/plutus_data.rs @@ -2,6 +2,8 @@ pub use pallas::codec::utils::Int; use pallas::codec::utils::KeyValuePairs; pub use pallas::ledger::primitives::{BigInt, BoundedBytes, Constr, MaybeIndefArray, PlutusData}; use tx3_lang::ir; +use std::collections::HashMap; + pub trait IntoData { fn as_data(&self) -> PlutusData; @@ -148,10 +150,27 @@ impl TryIntoData for ir::Expression { ir::Expression::Hash(x) => Ok(x.as_data()), ir::Expression::List(x) => x.try_as_data(), ir::Expression::Map(x) => x.try_as_data(), - x => Err(super::Error::CoerceError( - format!("{x:?}"), + ir::Expression::AdHocDirective(x) => match x.name.as_str() { + "cardano_payment_part" => Ok(extract_address_part(&x.data, 1..29)), + "cardano_staking_part" => Ok(extract_address_part(&x.data, 29..)), + _ => Ok(().as_data()), + }, + _ => Err(super::Error::CoerceError( + format!("{self:?}"), "PlutusData".to_string(), )), } } } + +fn extract_address_part(data: &HashMap, range: R) -> PlutusData +where + R: std::slice::SliceIndex<[u8], Output = [u8]>, +{ + data.get("address") + .and_then(|expr| match expr { + ir::Expression::Address(bytes) => bytes.get(range).map(|part| part.as_data()), + _ => None, + }) + .unwrap_or_else(|| ().as_data()) +} \ No newline at end of file diff --git a/crates/tx3-lang/src/cardano.rs b/crates/tx3-lang/src/cardano.rs index 77cd5861..143d4b5a 100644 --- a/crates/tx3-lang/src/cardano.rs +++ b/crates/tx3-lang/src/cardano.rs @@ -724,6 +724,18 @@ impl IntoLower for CardanoPublishBlock { } } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct CardanoPaymentPart { + pub address: Box, + pub span: Span, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct CardanoStakingPart { + pub address: Box, + pub span: Span, +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum CardanoBlock { VoteDelegationCertificate(VoteDelegationCertificate), @@ -733,6 +745,40 @@ pub enum CardanoBlock { NativeWitness(NativeWitnessBlock), TreasuryDonation(TreasuryDonationBlock), Publish(CardanoPublishBlock), + PaymentPart(CardanoPaymentPart), + StakingPart(CardanoStakingPart), +} + +impl AstNode for CardanoPaymentPart { + const RULE: Rule = Rule::cardano_payment_part; + + fn parse(pair: Pair) -> Result { + let span = pair.as_span().into(); + let mut inner = pair.into_inner(); + let address = DataExpr::parse(inner.next().unwrap())?.into(); + + Ok(CardanoPaymentPart { address, span }) + } + + fn span(&self) -> &Span { + &self.span + } +} + +impl AstNode for CardanoStakingPart { + const RULE: Rule = Rule::cardano_staking_part; + + fn parse(pair: Pair) -> Result { + let span = pair.as_span().into(); + let mut inner = pair.into_inner(); + let address = DataExpr::parse(inner.next().unwrap())?.into(); + + Ok(CardanoStakingPart { address, span }) + } + + fn span(&self) -> &Span { + &self.span + } } impl AstNode for CardanoBlock { @@ -764,6 +810,12 @@ impl AstNode for CardanoBlock { Rule::cardano_publish_block => { Ok(CardanoBlock::Publish(CardanoPublishBlock::parse(item)?)) } + Rule::cardano_payment_part => { + Ok(CardanoBlock::PaymentPart(CardanoPaymentPart::parse(item)?)) + } + Rule::cardano_staking_part => { + Ok(CardanoBlock::StakingPart(CardanoStakingPart::parse(item)?)) + } x => unreachable!("Unexpected rule in cardano_block: {:?}", x), } } @@ -777,10 +829,32 @@ impl AstNode for CardanoBlock { CardanoBlock::NativeWitness(x) => x.span(), CardanoBlock::TreasuryDonation(x) => x.span(), CardanoBlock::Publish(x) => x.span(), + CardanoBlock::PaymentPart(x) => x.span(), + CardanoBlock::StakingPart(x) => x.span(), } } } +impl Analyzable for CardanoPaymentPart { + fn analyze(&mut self, parent: Option>) -> AnalyzeReport { + self.address.analyze(parent) + } + + fn is_resolved(&self) -> bool { + self.address.is_resolved() + } +} + +impl Analyzable for CardanoStakingPart { + fn analyze(&mut self, parent: Option>) -> AnalyzeReport { + self.address.analyze(parent) + } + + fn is_resolved(&self) -> bool { + self.address.is_resolved() + } +} + impl Analyzable for CardanoBlock { fn analyze(&mut self, parent: Option>) -> AnalyzeReport { match self { @@ -791,6 +865,8 @@ impl Analyzable for CardanoBlock { CardanoBlock::NativeWitness(x) => x.analyze(parent), CardanoBlock::TreasuryDonation(x) => x.analyze(parent), CardanoBlock::Publish(x) => x.analyze(parent), + CardanoBlock::PaymentPart(x) => x.analyze(parent), + CardanoBlock::StakingPart(x) => x.analyze(parent), } } @@ -803,10 +879,46 @@ impl Analyzable for CardanoBlock { CardanoBlock::NativeWitness(x) => x.is_resolved(), Self::TreasuryDonation(x) => x.is_resolved(), CardanoBlock::Publish(x) => x.is_resolved(), + CardanoBlock::PaymentPart(x) => x.is_resolved(), + CardanoBlock::StakingPart(x) => x.is_resolved(), } } } +impl IntoLower for CardanoPaymentPart { + type Output = ir::AdHocDirective; + + fn into_lower( + &self, + ctx: &crate::lowering::Context, + ) -> Result { + let address_expr = self.address.into_lower(ctx)?; + let mut data = std::collections::HashMap::new(); + data.insert("address".to_string(), address_expr); + Ok(ir::AdHocDirective { + name: "cardano_payment_part".to_string(), + data, + }) + } +} + +impl IntoLower for CardanoStakingPart { + type Output = ir::AdHocDirective; + + fn into_lower( + &self, + ctx: &crate::lowering::Context, + ) -> Result { + let address_expr = self.address.into_lower(ctx)?; + let mut data = std::collections::HashMap::new(); + data.insert("address".to_string(), address_expr); + Ok(ir::AdHocDirective { + name: "cardano_staking_part".to_string(), + data, + }) + } +} + impl IntoLower for CardanoBlock { type Output = ir::AdHocDirective; @@ -822,6 +934,8 @@ impl IntoLower for CardanoBlock { CardanoBlock::NativeWitness(x) => x.into_lower(ctx), CardanoBlock::TreasuryDonation(x) => x.into_lower(ctx), CardanoBlock::Publish(x) => x.into_lower(ctx), + CardanoBlock::PaymentPart(x) => x.into_lower(ctx), + CardanoBlock::StakingPart(x) => x.into_lower(ctx), } } } diff --git a/crates/tx3-lang/src/tx3.pest b/crates/tx3-lang/src/tx3.pest index 448e0442..4ab29333 100644 --- a/crates/tx3-lang/src/tx3.pest +++ b/crates/tx3-lang/src/tx3.pest @@ -390,6 +390,9 @@ cardano_publish_block = { "}" } +cardano_payment_part = { "payment_part" ~ "(" ~ data_expr ~ ")" } +cardano_staking_part = { "staking_part" ~ "(" ~ data_expr ~ ")" } + cardano_block = { "cardano" ~ "::" ~ ( cardano_stake_delegation_certificate | @@ -398,7 +401,9 @@ cardano_block = { cardano_plutus_witness_block | cardano_native_witness_block | cardano_treasury_donation_block | - cardano_publish_block + cardano_publish_block | + cardano_payment_part | + cardano_staking_part ) } diff --git a/examples/cardano_witness.mint_from_plutus.tir b/examples/cardano_witness.mint_from_plutus.tir index 7f6c09cc..85165ace 100644 --- a/examples/cardano_witness.mint_from_plutus.tir +++ b/examples/cardano_witness.mint_from_plutus.tir @@ -201,9 +201,6 @@ { "name": "plutus_witness", "data": { - "version": { - "Number": 3 - }, "script": { "Bytes": [ 81, @@ -225,6 +222,9 @@ 174, 105 ] + }, + "version": { + "Number": 3 } } } diff --git a/examples/reference_script.publish_native.tir b/examples/reference_script.publish_native.tir index c90fbf85..a3527286 100644 --- a/examples/reference_script.publish_native.tir +++ b/examples/reference_script.publish_native.tir @@ -144,6 +144,19 @@ ] } }, + "script": { + "Bytes": [ + 130, + 1, + 129, + 130, + 4, + 0 + ] + }, + "version": { + "Number": 0 + }, "amount": { "Assets": [ { @@ -159,19 +172,6 @@ } } ] - }, - "script": { - "Bytes": [ - 130, - 1, - 129, - 130, - 4, - 0 - ] - }, - "version": { - "Number": 0 } } } diff --git a/examples/reference_script.publish_plutus.tir b/examples/reference_script.publish_plutus.tir index fab2edf1..987e9dad 100644 --- a/examples/reference_script.publish_plutus.tir +++ b/examples/reference_script.publish_plutus.tir @@ -136,17 +136,6 @@ { "name": "cardano_publish", "data": { - "version": { - "Number": 3 - }, - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } - }, "amount": { "Assets": [ { @@ -184,6 +173,17 @@ 174, 105 ] + }, + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, + "version": { + "Number": 3 } } } From 5d19fbe48edde8ba4bb2071800b1bb620fe71a51 Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Wed, 24 Sep 2025 17:38:10 -0300 Subject: [PATCH 2/7] test lowering and sintax fix --- crates/tx3-lang/src/analyzing.rs | 2 + crates/tx3-lang/src/ast.rs | 2 + crates/tx3-lang/src/cardano.rs | 78 ++++++-- crates/tx3-lang/src/lowering.rs | 3 + crates/tx3-lang/src/parsing.rs | 6 +- crates/tx3-lang/src/tx3.pest | 13 +- examples/party_serialization.transfer.tir | 187 +++++++++++++++++++ examples/party_serialization.tx3 | 30 +++ examples/reference_script.publish_native.tir | 6 +- examples/reference_script.publish_plutus.tir | 22 +-- examples/withdrawal.transfer.tir | 6 +- 11 files changed, 317 insertions(+), 38 deletions(-) create mode 100644 examples/party_serialization.transfer.tir create mode 100644 examples/party_serialization.tx3 diff --git a/crates/tx3-lang/src/analyzing.rs b/crates/tx3-lang/src/analyzing.rs index 03bc326f..681ca354 100644 --- a/crates/tx3-lang/src/analyzing.rs +++ b/crates/tx3-lang/src/analyzing.rs @@ -601,6 +601,7 @@ impl Analyzable for DataExpr { DataExpr::AnyAssetConstructor(x) => x.analyze(parent), DataExpr::MinUtxo(x) => x.analyze(parent), DataExpr::ConcatOp(x) => x.analyze(parent), + DataExpr::CardanoFunctions(x) => x.analyze(parent), _ => AnalyzeReport::default(), } } @@ -619,6 +620,7 @@ impl Analyzable for DataExpr { DataExpr::AnyAssetConstructor(x) => x.is_resolved(), DataExpr::MinUtxo(x) => x.is_resolved(), DataExpr::ConcatOp(x) => x.is_resolved(), + DataExpr::CardanoFunctions(x) => x.is_resolved(), _ => true, } } diff --git a/crates/tx3-lang/src/ast.rs b/crates/tx3-lang/src/ast.rs index 11bc0ecf..d63647c5 100644 --- a/crates/tx3-lang/src/ast.rs +++ b/crates/tx3-lang/src/ast.rs @@ -740,6 +740,7 @@ pub enum DataExpr { NegateOp(NegateOp), PropertyOp(PropertyOp), UtxoRef(UtxoRef), + CardanoFunctions(crate::cardano::CardanoFunctions), } impl DataExpr { @@ -775,6 +776,7 @@ impl DataExpr { DataExpr::UtxoRef(_) => Some(Type::UtxoRef), DataExpr::MinUtxo(_) => Some(Type::AnyAsset), DataExpr::ComputeTipSlot => Some(Type::Int), + DataExpr::CardanoFunctions(_) => Some(Type::Bytes), // Payment/staking parts return bytes } } } diff --git a/crates/tx3-lang/src/cardano.rs b/crates/tx3-lang/src/cardano.rs index 143d4b5a..b1e2c21c 100644 --- a/crates/tx3-lang/src/cardano.rs +++ b/crates/tx3-lang/src/cardano.rs @@ -736,6 +736,12 @@ pub struct CardanoStakingPart { pub span: Span, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum CardanoFunctions { + PaymentPart(CardanoPaymentPart), + StakingPart(CardanoStakingPart), +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum CardanoBlock { VoteDelegationCertificate(VoteDelegationCertificate), @@ -745,8 +751,6 @@ pub enum CardanoBlock { NativeWitness(NativeWitnessBlock), TreasuryDonation(TreasuryDonationBlock), Publish(CardanoPublishBlock), - PaymentPart(CardanoPaymentPart), - StakingPart(CardanoStakingPart), } impl AstNode for CardanoPaymentPart { @@ -810,12 +814,6 @@ impl AstNode for CardanoBlock { Rule::cardano_publish_block => { Ok(CardanoBlock::Publish(CardanoPublishBlock::parse(item)?)) } - Rule::cardano_payment_part => { - Ok(CardanoBlock::PaymentPart(CardanoPaymentPart::parse(item)?)) - } - Rule::cardano_staking_part => { - Ok(CardanoBlock::StakingPart(CardanoStakingPart::parse(item)?)) - } x => unreachable!("Unexpected rule in cardano_block: {:?}", x), } } @@ -829,8 +827,6 @@ impl AstNode for CardanoBlock { CardanoBlock::NativeWitness(x) => x.span(), CardanoBlock::TreasuryDonation(x) => x.span(), CardanoBlock::Publish(x) => x.span(), - CardanoBlock::PaymentPart(x) => x.span(), - CardanoBlock::StakingPart(x) => x.span(), } } } @@ -865,8 +861,6 @@ impl Analyzable for CardanoBlock { CardanoBlock::NativeWitness(x) => x.analyze(parent), CardanoBlock::TreasuryDonation(x) => x.analyze(parent), CardanoBlock::Publish(x) => x.analyze(parent), - CardanoBlock::PaymentPart(x) => x.analyze(parent), - CardanoBlock::StakingPart(x) => x.analyze(parent), } } @@ -879,8 +873,6 @@ impl Analyzable for CardanoBlock { CardanoBlock::NativeWitness(x) => x.is_resolved(), Self::TreasuryDonation(x) => x.is_resolved(), CardanoBlock::Publish(x) => x.is_resolved(), - CardanoBlock::PaymentPart(x) => x.is_resolved(), - CardanoBlock::StakingPart(x) => x.is_resolved(), } } } @@ -919,6 +911,62 @@ impl IntoLower for CardanoStakingPart { } } +impl AstNode for CardanoFunctions { + const RULE: Rule = Rule::cardano_functions; + + fn parse(pair: Pair) -> Result { + let mut inner = pair.into_inner(); + let function_pair = inner.next().unwrap(); + + match function_pair.as_rule() { + Rule::cardano_payment_part => { + Ok(CardanoFunctions::PaymentPart(CardanoPaymentPart::parse(function_pair)?)) + } + Rule::cardano_staking_part => { + Ok(CardanoFunctions::StakingPart(CardanoStakingPart::parse(function_pair)?)) + } + x => unreachable!("Unexpected rule in cardano_functions: {:?}", x), + } + } + + fn span(&self) -> &Span { + match self { + CardanoFunctions::PaymentPart(x) => x.span(), + CardanoFunctions::StakingPart(x) => x.span(), + } + } +} + +impl Analyzable for CardanoFunctions { + fn analyze(&mut self, parent: Option>) -> AnalyzeReport { + match self { + CardanoFunctions::PaymentPart(x) => x.analyze(parent), + CardanoFunctions::StakingPart(x) => x.analyze(parent), + } + } + + fn is_resolved(&self) -> bool { + match self { + CardanoFunctions::PaymentPart(x) => x.is_resolved(), + CardanoFunctions::StakingPart(x) => x.is_resolved(), + } + } +} + +impl IntoLower for CardanoFunctions { + type Output = ir::AdHocDirective; + + fn into_lower( + &self, + ctx: &crate::lowering::Context, + ) -> Result { + match self { + CardanoFunctions::PaymentPart(x) => x.into_lower(ctx), + CardanoFunctions::StakingPart(x) => x.into_lower(ctx), + } + } +} + impl IntoLower for CardanoBlock { type Output = ir::AdHocDirective; @@ -934,8 +982,6 @@ impl IntoLower for CardanoBlock { CardanoBlock::NativeWitness(x) => x.into_lower(ctx), CardanoBlock::TreasuryDonation(x) => x.into_lower(ctx), CardanoBlock::Publish(x) => x.into_lower(ctx), - CardanoBlock::PaymentPart(x) => x.into_lower(ctx), - CardanoBlock::StakingPart(x) => x.into_lower(ctx), } } } diff --git a/crates/tx3-lang/src/lowering.rs b/crates/tx3-lang/src/lowering.rs index c4d53b0f..55e9c007 100644 --- a/crates/tx3-lang/src/lowering.rs +++ b/crates/tx3-lang/src/lowering.rs @@ -472,6 +472,7 @@ impl IntoLower for ast::DataExpr { ast::DataExpr::ComputeTipSlot => { ir::Expression::EvalCompiler(Box::new(ir::CompilerOp::ComputeTipSlot)) } + ast::DataExpr::CardanoFunctions(x) => ir::Expression::AdHocDirective(Box::new(x.into_lower(ctx)?)), }; Ok(out) @@ -935,4 +936,6 @@ mod tests { test_lowering!(donation); test_lowering!(list_concat); + + test_lowering!(party_serialization); } diff --git a/crates/tx3-lang/src/parsing.rs b/crates/tx3-lang/src/parsing.rs index f48cd1ae..c78baf43 100644 --- a/crates/tx3-lang/src/parsing.rs +++ b/crates/tx3-lang/src/parsing.rs @@ -14,7 +14,7 @@ use pest_derive::Parser; use crate::{ ast::*, - cardano::{PlutusWitnessBlock, PlutusWitnessField}, + cardano::{CardanoFunctions, PlutusWitnessBlock, PlutusWitnessField}, }; #[derive(Parser)] #[grammar = "tx3.pest"] @@ -1227,6 +1227,7 @@ impl AstNode for DataExpr { Rule::concat_constructor => DataExpr::concat_constructor_parse(x), Rule::min_utxo => DataExpr::min_utxo_parse(x), Rule::tip_slot => DataExpr::tip_slot_parse(x), + Rule::cardano_functions => Ok(DataExpr::CardanoFunctions(CardanoFunctions::parse(x)?)), Rule::data_expr => DataExpr::parse(x), x => unreachable!("unexpected rule as data primary: {:?}", x), }) @@ -1268,7 +1269,8 @@ impl AstNode for DataExpr { DataExpr::PropertyOp(x) => &x.span, DataExpr::UtxoRef(x) => x.span(), DataExpr::MinUtxo(x) => x.span(), - DataExpr::ComputeTipSlot => &Span::DUMMY, // TODO + DataExpr::ComputeTipSlot => &Span::DUMMY, + DataExpr::CardanoFunctions(x) => x.span(), } } } diff --git a/crates/tx3-lang/src/tx3.pest b/crates/tx3-lang/src/tx3.pest index 4ab29333..b6bbb39e 100644 --- a/crates/tx3-lang/src/tx3.pest +++ b/crates/tx3-lang/src/tx3.pest @@ -152,6 +152,7 @@ data_expr = { data_prefix* ~ data_primary ~ data_postfix* ~ (data_infix ~ data_p string | min_utxo | tip_slot | + cardano_functions | struct_constructor | list_constructor | map_constructor | @@ -393,6 +394,14 @@ cardano_publish_block = { cardano_payment_part = { "payment_part" ~ "(" ~ data_expr ~ ")" } cardano_staking_part = { "staking_part" ~ "(" ~ data_expr ~ ")" } +cardano_functions = { + "cardano" ~ "::" ~ ( + cardano_payment_part | + cardano_staking_part + ) +} + + cardano_block = { "cardano" ~ "::" ~ ( cardano_stake_delegation_certificate | @@ -401,9 +410,7 @@ cardano_block = { cardano_plutus_witness_block | cardano_native_witness_block | cardano_treasury_donation_block | - cardano_publish_block | - cardano_payment_part | - cardano_staking_part + cardano_publish_block ) } diff --git a/examples/party_serialization.transfer.tir b/examples/party_serialization.transfer.tir new file mode 100644 index 00000000..9fe8c701 --- /dev/null +++ b/examples/party_serialization.transfer.tir @@ -0,0 +1,187 @@ +{ + "fees": { + "EvalParam": "ExpectFees" + }, + "references": [], + "inputs": [ + { + "name": "source", + "utxos": { + "EvalParam": { + "ExpectInput": [ + "source", + { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, + "min_amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + }, + "ref": "None", + "many": false, + "collateral": false + } + ] + } + }, + "redeemer": "None" + } + ], + "outputs": [ + { + "address": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, + "datum": "None", + "amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + } + }, + { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, + "datum": { + "Struct": { + "constructor": 0, + "fields": [ + { + "AdHocDirective": { + "name": "cardano_payment_part", + "data": { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + } + } + } + } + ] + } + }, + "amount": { + "EvalBuiltIn": { + "Sub": [ + { + "EvalBuiltIn": { + "Sub": [ + { + "EvalCoerce": { + "IntoAssets": { + "EvalParam": { + "ExpectInput": [ + "source", + { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, + "min_amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + }, + "ref": "None", + "many": false, + "collateral": false + } + ] + } + } + } + }, + { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + } + ] + } + }, + { + "EvalParam": "ExpectFees" + } + ] + } + } + } + ], + "validity": null, + "mints": [], + "burns": [], + "adhoc": [], + "collateral": [], + "signers": null, + "metadata": [] +} \ No newline at end of file diff --git a/examples/party_serialization.tx3 b/examples/party_serialization.tx3 new file mode 100644 index 00000000..431c66ee --- /dev/null +++ b/examples/party_serialization.tx3 @@ -0,0 +1,30 @@ + +type Datum { + owner: Bytes, +} + +party Sender; + +party Receiver; + +tx transfer( + quantity: Int +) { + input source { + from: Sender, + min_amount: Ada(quantity), + } + + output { + to: Receiver, + amount: Ada(quantity), + } + + output { + to: Sender, + amount: source - Ada(quantity) - fees, + datum: Datum { + owner: cardano::payment_part(Sender), + }, + } +} \ No newline at end of file diff --git a/examples/reference_script.publish_native.tir b/examples/reference_script.publish_native.tir index a3527286..345a5d43 100644 --- a/examples/reference_script.publish_native.tir +++ b/examples/reference_script.publish_native.tir @@ -154,9 +154,6 @@ 0 ] }, - "version": { - "Number": 0 - }, "amount": { "Assets": [ { @@ -172,6 +169,9 @@ } } ] + }, + "version": { + "Number": 0 } } } diff --git a/examples/reference_script.publish_plutus.tir b/examples/reference_script.publish_plutus.tir index 987e9dad..f67d9fc1 100644 --- a/examples/reference_script.publish_plutus.tir +++ b/examples/reference_script.publish_plutus.tir @@ -136,6 +136,9 @@ { "name": "cardano_publish", "data": { + "version": { + "Number": 3 + }, "amount": { "Assets": [ { @@ -152,6 +155,14 @@ } ] }, + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, "script": { "Bytes": [ 81, @@ -173,17 +184,6 @@ 174, 105 ] - }, - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } - }, - "version": { - "Number": 3 } } } diff --git a/examples/withdrawal.transfer.tir b/examples/withdrawal.transfer.tir index be726c97..5130bab6 100644 --- a/examples/withdrawal.transfer.tir +++ b/examples/withdrawal.transfer.tir @@ -163,9 +163,6 @@ { "name": "withdrawal", "data": { - "amount": { - "Number": 0 - }, "credential": { "EvalParam": { "ExpectValue": [ @@ -174,6 +171,9 @@ ] } }, + "amount": { + "Number": 0 + }, "redeemer": { "Struct": { "constructor": 0, From 6695bfe350a17d754436b2518015852d969f60d5 Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Wed, 24 Sep 2025 17:39:21 -0300 Subject: [PATCH 3/7] test parsing --- crates/tx3-lang/src/parsing.rs | 2 + examples/party_serialization.ast | 409 +++++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+) create mode 100644 examples/party_serialization.ast diff --git a/crates/tx3-lang/src/parsing.rs b/crates/tx3-lang/src/parsing.rs index c78baf43..a4cdacf6 100644 --- a/crates/tx3-lang/src/parsing.rs +++ b/crates/tx3-lang/src/parsing.rs @@ -2658,4 +2658,6 @@ mod tests { test_parsing!(donation); test_parsing!(list_concat); + + test_parsing!(party_serialization); } diff --git a/examples/party_serialization.ast b/examples/party_serialization.ast new file mode 100644 index 00000000..074c5acc --- /dev/null +++ b/examples/party_serialization.ast @@ -0,0 +1,409 @@ +{ + "env": null, + "txs": [ + { + "name": { + "value": "transfer", + "span": { + "dummy": false, + "start": 68, + "end": 76 + } + }, + "parameters": { + "parameters": [ + { + "name": { + "value": "quantity", + "span": { + "dummy": false, + "start": 82, + "end": 90 + } + }, + "type": "Int" + } + ], + "span": { + "dummy": false, + "start": 76, + "end": 97 + } + }, + "locals": null, + "references": [], + "inputs": [ + { + "name": "source", + "many": false, + "fields": [ + { + "From": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 133, + "end": 139 + } + } + } + }, + { + "MinAmount": { + "StaticAssetConstructor": { + "type": { + "value": "Ada", + "span": { + "dummy": false, + "start": 161, + "end": 164 + } + }, + "amount": { + "Identifier": { + "value": "quantity", + "span": { + "dummy": false, + "start": 165, + "end": 173 + } + } + }, + "span": { + "dummy": false, + "start": 161, + "end": 174 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 104, + "end": 181 + } + } + ], + "outputs": [ + { + "name": null, + "fields": [ + { + "To": { + "Identifier": { + "value": "Receiver", + "span": { + "dummy": false, + "start": 208, + "end": 216 + } + } + } + }, + { + "Amount": { + "StaticAssetConstructor": { + "type": { + "value": "Ada", + "span": { + "dummy": false, + "start": 234, + "end": 237 + } + }, + "amount": { + "Identifier": { + "value": "quantity", + "span": { + "dummy": false, + "start": 238, + "end": 246 + } + } + }, + "span": { + "dummy": false, + "start": 234, + "end": 247 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 187, + "end": 254 + } + }, + { + "name": null, + "fields": [ + { + "To": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 281, + "end": 287 + } + } + } + }, + { + "Amount": { + "SubOp": { + "lhs": { + "SubOp": { + "lhs": { + "Identifier": { + "value": "source", + "span": { + "dummy": false, + "start": 305, + "end": 311 + } + } + }, + "rhs": { + "StaticAssetConstructor": { + "type": { + "value": "Ada", + "span": { + "dummy": false, + "start": 314, + "end": 317 + } + }, + "amount": { + "Identifier": { + "value": "quantity", + "span": { + "dummy": false, + "start": 318, + "end": 326 + } + } + }, + "span": { + "dummy": false, + "start": 314, + "end": 327 + } + } + }, + "span": { + "dummy": false, + "start": 312, + "end": 313 + } + } + }, + "rhs": { + "Identifier": { + "value": "fees", + "span": { + "dummy": false, + "start": 330, + "end": 334 + } + } + }, + "span": { + "dummy": false, + "start": 328, + "end": 329 + } + } + } + }, + { + "Datum": { + "StructConstructor": { + "type": { + "value": "Datum", + "span": { + "dummy": false, + "start": 351, + "end": 356 + } + }, + "case": { + "name": { + "value": "Default", + "span": { + "dummy": true, + "start": 0, + "end": 0 + } + }, + "fields": [ + { + "name": { + "value": "owner", + "span": { + "dummy": false, + "start": 369, + "end": 374 + } + }, + "value": { + "CardanoFunctions": { + "PaymentPart": { + "address": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 398, + "end": 404 + } + } + }, + "span": { + "dummy": false, + "start": 385, + "end": 405 + } + } + } + }, + "span": { + "dummy": false, + "start": 369, + "end": 405 + } + } + ], + "spread": null, + "span": { + "dummy": false, + "start": 357, + "end": 416 + } + }, + "span": { + "dummy": false, + "start": 351, + "end": 416 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 260, + "end": 423 + } + } + ], + "validity": null, + "mints": [], + "burns": [], + "signers": null, + "adhoc": [], + "span": { + "dummy": false, + "start": 65, + "end": 425 + }, + "collateral": [], + "metadata": null + } + ], + "types": [ + { + "name": { + "value": "Datum", + "span": { + "dummy": false, + "start": 6, + "end": 11 + } + }, + "cases": [ + { + "name": { + "value": "Default", + "span": { + "dummy": true, + "start": 0, + "end": 0 + } + }, + "fields": [ + { + "name": { + "value": "owner", + "span": { + "dummy": false, + "start": 16, + "end": 21 + } + }, + "type": "Bytes", + "span": { + "dummy": false, + "start": 16, + "end": 28 + } + } + ], + "span": { + "dummy": false, + "start": 1, + "end": 31 + } + } + ], + "span": { + "dummy": false, + "start": 1, + "end": 31 + } + } + ], + "assets": [], + "parties": [ + { + "name": { + "value": "Sender", + "span": { + "dummy": false, + "start": 39, + "end": 45 + } + }, + "span": { + "dummy": false, + "start": 33, + "end": 46 + } + }, + { + "name": { + "value": "Receiver", + "span": { + "dummy": false, + "start": 54, + "end": 62 + } + }, + "span": { + "dummy": false, + "start": 48, + "end": 63 + } + } + ], + "policies": [], + "span": { + "dummy": false, + "start": 0, + "end": 425 + } +} \ No newline at end of file From 799df1a16974d9e9027c2c6b8877c9be41a76ceb Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Wed, 1 Oct 2025 14:58:32 -0300 Subject: [PATCH 4/7] sintax rename of functions and specific data expression for each one --- crates/tx3-cardano/src/compile/plutus_data.rs | 4 +- crates/tx3-lang/src/analyzing.rs | 6 +- crates/tx3-lang/src/ast.rs | 6 +- crates/tx3-lang/src/cardano.rs | 102 +++++------------- crates/tx3-lang/src/lowering.rs | 3 +- crates/tx3-lang/src/parsing.rs | 11 +- crates/tx3-lang/src/tx3.pest | 8 +- examples/cardano_witness.mint_from_plutus.tir | 6 +- examples/party_serialization.ast | 28 +++-- examples/party_serialization.transfer.tir | 2 +- examples/reference_script.publish_native.tir | 20 ++-- examples/reference_script.publish_plutus.tir | 6 +- examples/withdrawal.transfer.tir | 18 ++-- 13 files changed, 88 insertions(+), 132 deletions(-) diff --git a/crates/tx3-cardano/src/compile/plutus_data.rs b/crates/tx3-cardano/src/compile/plutus_data.rs index 854b9c0d..1cbd2da5 100644 --- a/crates/tx3-cardano/src/compile/plutus_data.rs +++ b/crates/tx3-cardano/src/compile/plutus_data.rs @@ -151,8 +151,8 @@ impl TryIntoData for ir::Expression { ir::Expression::List(x) => x.try_as_data(), ir::Expression::Map(x) => x.try_as_data(), ir::Expression::AdHocDirective(x) => match x.name.as_str() { - "cardano_payment_part" => Ok(extract_address_part(&x.data, 1..29)), - "cardano_staking_part" => Ok(extract_address_part(&x.data, 29..)), + "cardano_address_payment_part" => Ok(extract_address_part(&x.data, 1..29)), + "cardano_address_staking_part" => Ok(extract_address_part(&x.data, 29..)), _ => Ok(().as_data()), }, _ => Err(super::Error::CoerceError( diff --git a/crates/tx3-lang/src/analyzing.rs b/crates/tx3-lang/src/analyzing.rs index 681ca354..b81263b1 100644 --- a/crates/tx3-lang/src/analyzing.rs +++ b/crates/tx3-lang/src/analyzing.rs @@ -601,7 +601,8 @@ impl Analyzable for DataExpr { DataExpr::AnyAssetConstructor(x) => x.analyze(parent), DataExpr::MinUtxo(x) => x.analyze(parent), DataExpr::ConcatOp(x) => x.analyze(parent), - DataExpr::CardanoFunctions(x) => x.analyze(parent), + DataExpr::AddressPaymentPart(x) => x.analyze(parent), + DataExpr::AddressStakingPart(x) => x.analyze(parent), _ => AnalyzeReport::default(), } } @@ -620,7 +621,8 @@ impl Analyzable for DataExpr { DataExpr::AnyAssetConstructor(x) => x.is_resolved(), DataExpr::MinUtxo(x) => x.is_resolved(), DataExpr::ConcatOp(x) => x.is_resolved(), - DataExpr::CardanoFunctions(x) => x.is_resolved(), + DataExpr::AddressPaymentPart(x) => x.is_resolved(), + DataExpr::AddressStakingPart(x) => x.is_resolved(), _ => true, } } diff --git a/crates/tx3-lang/src/ast.rs b/crates/tx3-lang/src/ast.rs index d63647c5..f90e445c 100644 --- a/crates/tx3-lang/src/ast.rs +++ b/crates/tx3-lang/src/ast.rs @@ -740,7 +740,8 @@ pub enum DataExpr { NegateOp(NegateOp), PropertyOp(PropertyOp), UtxoRef(UtxoRef), - CardanoFunctions(crate::cardano::CardanoFunctions), + AddressPaymentPart(crate::cardano::AddressPaymentPart), + AddressStakingPart(crate::cardano::AddressStakingPart), } impl DataExpr { @@ -776,7 +777,8 @@ impl DataExpr { DataExpr::UtxoRef(_) => Some(Type::UtxoRef), DataExpr::MinUtxo(_) => Some(Type::AnyAsset), DataExpr::ComputeTipSlot => Some(Type::Int), - DataExpr::CardanoFunctions(_) => Some(Type::Bytes), // Payment/staking parts return bytes + DataExpr::AddressPaymentPart(_) => Some(Type::Bytes), + DataExpr::AddressStakingPart(_) => Some(Type::Bytes), } } } diff --git a/crates/tx3-lang/src/cardano.rs b/crates/tx3-lang/src/cardano.rs index b1e2c21c..a26b531b 100644 --- a/crates/tx3-lang/src/cardano.rs +++ b/crates/tx3-lang/src/cardano.rs @@ -725,23 +725,33 @@ impl IntoLower for CardanoPublishBlock { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub struct CardanoPaymentPart { +pub struct AddressPaymentPart { pub address: Box, pub span: Span, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub struct CardanoStakingPart { +pub struct AddressStakingPart { pub address: Box, pub span: Span, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub enum CardanoFunctions { - PaymentPart(CardanoPaymentPart), - StakingPart(CardanoStakingPart), +pub fn parse_cardano_function(pair: Pair) -> Result { + let mut inner = pair.into_inner(); + let function_pair = inner.next().unwrap(); + + match function_pair.as_rule() { + Rule::cardano_address_payment_part => { + Ok(DataExpr::AddressPaymentPart(AddressPaymentPart::parse(function_pair)?)) + } + Rule::cardano_address_staking_part => { + Ok(DataExpr::AddressStakingPart(AddressStakingPart::parse(function_pair)?)) + } + x => unreachable!("Unexpected rule in cardano_functions: {:?}", x), + } } + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum CardanoBlock { VoteDelegationCertificate(VoteDelegationCertificate), @@ -753,15 +763,15 @@ pub enum CardanoBlock { Publish(CardanoPublishBlock), } -impl AstNode for CardanoPaymentPart { - const RULE: Rule = Rule::cardano_payment_part; +impl AstNode for AddressPaymentPart { + const RULE: Rule = Rule::cardano_address_payment_part; fn parse(pair: Pair) -> Result { let span = pair.as_span().into(); let mut inner = pair.into_inner(); let address = DataExpr::parse(inner.next().unwrap())?.into(); - Ok(CardanoPaymentPart { address, span }) + Ok(AddressPaymentPart { address, span }) } fn span(&self) -> &Span { @@ -769,15 +779,15 @@ impl AstNode for CardanoPaymentPart { } } -impl AstNode for CardanoStakingPart { - const RULE: Rule = Rule::cardano_staking_part; +impl AstNode for AddressStakingPart { + const RULE: Rule = Rule::cardano_address_staking_part; fn parse(pair: Pair) -> Result { let span = pair.as_span().into(); let mut inner = pair.into_inner(); let address = DataExpr::parse(inner.next().unwrap())?.into(); - Ok(CardanoStakingPart { address, span }) + Ok(AddressStakingPart { address, span }) } fn span(&self) -> &Span { @@ -831,7 +841,7 @@ impl AstNode for CardanoBlock { } } -impl Analyzable for CardanoPaymentPart { +impl Analyzable for AddressPaymentPart { fn analyze(&mut self, parent: Option>) -> AnalyzeReport { self.address.analyze(parent) } @@ -841,7 +851,7 @@ impl Analyzable for CardanoPaymentPart { } } -impl Analyzable for CardanoStakingPart { +impl Analyzable for AddressStakingPart { fn analyze(&mut self, parent: Option>) -> AnalyzeReport { self.address.analyze(parent) } @@ -877,7 +887,7 @@ impl Analyzable for CardanoBlock { } } -impl IntoLower for CardanoPaymentPart { +impl IntoLower for AddressPaymentPart { type Output = ir::AdHocDirective; fn into_lower( @@ -888,13 +898,13 @@ impl IntoLower for CardanoPaymentPart { let mut data = std::collections::HashMap::new(); data.insert("address".to_string(), address_expr); Ok(ir::AdHocDirective { - name: "cardano_payment_part".to_string(), + name: "cardano_address_payment_part".to_string(), data, }) } } -impl IntoLower for CardanoStakingPart { +impl IntoLower for AddressStakingPart { type Output = ir::AdHocDirective; fn into_lower( @@ -905,68 +915,12 @@ impl IntoLower for CardanoStakingPart { let mut data = std::collections::HashMap::new(); data.insert("address".to_string(), address_expr); Ok(ir::AdHocDirective { - name: "cardano_staking_part".to_string(), + name: "cardano_address_staking_part".to_string(), data, }) } } -impl AstNode for CardanoFunctions { - const RULE: Rule = Rule::cardano_functions; - - fn parse(pair: Pair) -> Result { - let mut inner = pair.into_inner(); - let function_pair = inner.next().unwrap(); - - match function_pair.as_rule() { - Rule::cardano_payment_part => { - Ok(CardanoFunctions::PaymentPart(CardanoPaymentPart::parse(function_pair)?)) - } - Rule::cardano_staking_part => { - Ok(CardanoFunctions::StakingPart(CardanoStakingPart::parse(function_pair)?)) - } - x => unreachable!("Unexpected rule in cardano_functions: {:?}", x), - } - } - - fn span(&self) -> &Span { - match self { - CardanoFunctions::PaymentPart(x) => x.span(), - CardanoFunctions::StakingPart(x) => x.span(), - } - } -} - -impl Analyzable for CardanoFunctions { - fn analyze(&mut self, parent: Option>) -> AnalyzeReport { - match self { - CardanoFunctions::PaymentPart(x) => x.analyze(parent), - CardanoFunctions::StakingPart(x) => x.analyze(parent), - } - } - - fn is_resolved(&self) -> bool { - match self { - CardanoFunctions::PaymentPart(x) => x.is_resolved(), - CardanoFunctions::StakingPart(x) => x.is_resolved(), - } - } -} - -impl IntoLower for CardanoFunctions { - type Output = ir::AdHocDirective; - - fn into_lower( - &self, - ctx: &crate::lowering::Context, - ) -> Result { - match self { - CardanoFunctions::PaymentPart(x) => x.into_lower(ctx), - CardanoFunctions::StakingPart(x) => x.into_lower(ctx), - } - } -} - impl IntoLower for CardanoBlock { type Output = ir::AdHocDirective; diff --git a/crates/tx3-lang/src/lowering.rs b/crates/tx3-lang/src/lowering.rs index 55e9c007..33e31d76 100644 --- a/crates/tx3-lang/src/lowering.rs +++ b/crates/tx3-lang/src/lowering.rs @@ -472,7 +472,8 @@ impl IntoLower for ast::DataExpr { ast::DataExpr::ComputeTipSlot => { ir::Expression::EvalCompiler(Box::new(ir::CompilerOp::ComputeTipSlot)) } - ast::DataExpr::CardanoFunctions(x) => ir::Expression::AdHocDirective(Box::new(x.into_lower(ctx)?)), + ast::DataExpr::AddressPaymentPart(x) => ir::Expression::AdHocDirective(Box::new(x.into_lower(ctx)?)), + ast::DataExpr::AddressStakingPart(x) => ir::Expression::AdHocDirective(Box::new(x.into_lower(ctx)?)), }; Ok(out) diff --git a/crates/tx3-lang/src/parsing.rs b/crates/tx3-lang/src/parsing.rs index a4cdacf6..60e2661d 100644 --- a/crates/tx3-lang/src/parsing.rs +++ b/crates/tx3-lang/src/parsing.rs @@ -12,10 +12,8 @@ use pest::{ }; use pest_derive::Parser; -use crate::{ - ast::*, - cardano::{CardanoFunctions, PlutusWitnessBlock, PlutusWitnessField}, -}; +use crate::ast::*; + #[derive(Parser)] #[grammar = "tx3.pest"] pub(crate) struct Tx3Grammar; @@ -1227,7 +1225,7 @@ impl AstNode for DataExpr { Rule::concat_constructor => DataExpr::concat_constructor_parse(x), Rule::min_utxo => DataExpr::min_utxo_parse(x), Rule::tip_slot => DataExpr::tip_slot_parse(x), - Rule::cardano_functions => Ok(DataExpr::CardanoFunctions(CardanoFunctions::parse(x)?)), + Rule::cardano_functions => crate::cardano::parse_cardano_function(x), Rule::data_expr => DataExpr::parse(x), x => unreachable!("unexpected rule as data primary: {:?}", x), }) @@ -1270,7 +1268,8 @@ impl AstNode for DataExpr { DataExpr::UtxoRef(x) => x.span(), DataExpr::MinUtxo(x) => x.span(), DataExpr::ComputeTipSlot => &Span::DUMMY, - DataExpr::CardanoFunctions(x) => x.span(), + DataExpr::AddressPaymentPart(x) => x.span(), + DataExpr::AddressStakingPart(x) => x.span(), } } } diff --git a/crates/tx3-lang/src/tx3.pest b/crates/tx3-lang/src/tx3.pest index b6bbb39e..96a052ff 100644 --- a/crates/tx3-lang/src/tx3.pest +++ b/crates/tx3-lang/src/tx3.pest @@ -391,13 +391,13 @@ cardano_publish_block = { "}" } -cardano_payment_part = { "payment_part" ~ "(" ~ data_expr ~ ")" } -cardano_staking_part = { "staking_part" ~ "(" ~ data_expr ~ ")" } +cardano_address_payment_part = { "payment_part" ~ "(" ~ data_expr ~ ")" } +cardano_address_staking_part = { "staking_part" ~ "(" ~ data_expr ~ ")" } cardano_functions = { "cardano" ~ "::" ~ ( - cardano_payment_part | - cardano_staking_part + cardano_address_payment_part | + cardano_address_staking_part ) } diff --git a/examples/cardano_witness.mint_from_plutus.tir b/examples/cardano_witness.mint_from_plutus.tir index 85165ace..7f6c09cc 100644 --- a/examples/cardano_witness.mint_from_plutus.tir +++ b/examples/cardano_witness.mint_from_plutus.tir @@ -201,6 +201,9 @@ { "name": "plutus_witness", "data": { + "version": { + "Number": 3 + }, "script": { "Bytes": [ 81, @@ -222,9 +225,6 @@ 174, 105 ] - }, - "version": { - "Number": 3 } } } diff --git a/examples/party_serialization.ast b/examples/party_serialization.ast index 074c5acc..a86a1fc1 100644 --- a/examples/party_serialization.ast +++ b/examples/party_serialization.ast @@ -251,23 +251,21 @@ } }, "value": { - "CardanoFunctions": { - "PaymentPart": { - "address": { - "Identifier": { - "value": "Sender", - "span": { - "dummy": false, - "start": 398, - "end": 404 - } + "AddressPaymentPart": { + "address": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 398, + "end": 404 } - }, - "span": { - "dummy": false, - "start": 385, - "end": 405 } + }, + "span": { + "dummy": false, + "start": 385, + "end": 405 } } }, diff --git a/examples/party_serialization.transfer.tir b/examples/party_serialization.transfer.tir index 9fe8c701..9b413f51 100644 --- a/examples/party_serialization.transfer.tir +++ b/examples/party_serialization.transfer.tir @@ -88,7 +88,7 @@ "fields": [ { "AdHocDirective": { - "name": "cardano_payment_part", + "name": "cardano_address_payment_part", "data": { "address": { "EvalParam": { diff --git a/examples/reference_script.publish_native.tir b/examples/reference_script.publish_native.tir index 345a5d43..6c2349db 100644 --- a/examples/reference_script.publish_native.tir +++ b/examples/reference_script.publish_native.tir @@ -136,13 +136,8 @@ { "name": "cardano_publish", "data": { - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } + "version": { + "Number": 0 }, "script": { "Bytes": [ @@ -154,6 +149,14 @@ 0 ] }, + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, "amount": { "Assets": [ { @@ -169,9 +172,6 @@ } } ] - }, - "version": { - "Number": 0 } } } diff --git a/examples/reference_script.publish_plutus.tir b/examples/reference_script.publish_plutus.tir index f67d9fc1..70e3979c 100644 --- a/examples/reference_script.publish_plutus.tir +++ b/examples/reference_script.publish_plutus.tir @@ -136,9 +136,6 @@ { "name": "cardano_publish", "data": { - "version": { - "Number": 3 - }, "amount": { "Assets": [ { @@ -155,6 +152,9 @@ } ] }, + "version": { + "Number": 3 + }, "to": { "EvalParam": { "ExpectValue": [ diff --git a/examples/withdrawal.transfer.tir b/examples/withdrawal.transfer.tir index 5130bab6..fb2ac831 100644 --- a/examples/withdrawal.transfer.tir +++ b/examples/withdrawal.transfer.tir @@ -163,6 +163,15 @@ { "name": "withdrawal", "data": { + "redeemer": { + "Struct": { + "constructor": 0, + "fields": [] + } + }, + "amount": { + "Number": 0 + }, "credential": { "EvalParam": { "ExpectValue": [ @@ -170,15 +179,6 @@ "Address" ] } - }, - "amount": { - "Number": 0 - }, - "redeemer": { - "Struct": { - "constructor": 0, - "fields": [] - } } } } From aaf131a6554b5cea5d70498ddc74cc50bd9e4090 Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Thu, 16 Oct 2025 17:54:11 -0300 Subject: [PATCH 5/7] update of extracting part functions --- crates/tx3-cardano/src/compile/plutus_data.rs | 68 ++++++++++++++++--- examples/reference_script.publish_native.tir | 6 +- examples/reference_script.publish_plutus.tir | 16 ++--- examples/withdrawal.transfer.tir | 16 ++--- 4 files changed, 76 insertions(+), 30 deletions(-) diff --git a/crates/tx3-cardano/src/compile/plutus_data.rs b/crates/tx3-cardano/src/compile/plutus_data.rs index 1cbd2da5..0d804b59 100644 --- a/crates/tx3-cardano/src/compile/plutus_data.rs +++ b/crates/tx3-cardano/src/compile/plutus_data.rs @@ -1,10 +1,9 @@ pub use pallas::codec::utils::Int; -use pallas::codec::utils::KeyValuePairs; +use pallas::{codec::utils::KeyValuePairs, ledger::addresses}; pub use pallas::ledger::primitives::{BigInt, BoundedBytes, Constr, MaybeIndefArray, PlutusData}; use tx3_lang::ir; use std::collections::HashMap; - pub trait IntoData { fn as_data(&self) -> PlutusData; } @@ -151,8 +150,8 @@ impl TryIntoData for ir::Expression { ir::Expression::List(x) => x.try_as_data(), ir::Expression::Map(x) => x.try_as_data(), ir::Expression::AdHocDirective(x) => match x.name.as_str() { - "cardano_address_payment_part" => Ok(extract_address_part(&x.data, 1..29)), - "cardano_address_staking_part" => Ok(extract_address_part(&x.data, 29..)), + "cardano_address_payment_part" => address_payment_part(&x.data), + "cardano_address_staking_part" => address_staking_part(&x.data), _ => Ok(().as_data()), }, _ => Err(super::Error::CoerceError( @@ -163,14 +162,61 @@ impl TryIntoData for ir::Expression { } } -fn extract_address_part(data: &HashMap, range: R) -> PlutusData -where - R: std::slice::SliceIndex<[u8], Output = [u8]>, -{ +fn extract_address(data: &HashMap) -> Result { data.get("address") + .ok_or_else(|| super::Error::CoerceError( + "Address field not found in data".to_string(), + "Address".to_string(), + )) .and_then(|expr| match expr { - ir::Expression::Address(bytes) => bytes.get(range).map(|part| part.as_data()), - _ => None, + ir::Expression::Address(bytes) => { + addresses::Address::from_bytes(bytes) + .map_err(|_| super::Error::CoerceError( + "Invalid address bytes".to_string(), + "Address".to_string(), + )) + } + _ => Err(super::Error::CoerceError( + format!("Expected Address expression, found {:?}", expr), + "Address".to_string(), + )), }) - .unwrap_or_else(|| ().as_data()) +} + +fn address_payment_part(data: &HashMap) -> Result { + let addr = extract_address(data)?; + + match addr { + addresses::Address::Shelley(shelley_addr) => { + // Extract the payment credential from the Shelley address + let payment_bytes = shelley_addr.payment().to_vec(); + Ok(payment_bytes.as_data()) + } + addresses::Address::Byron(byron_addr) => { + // Extract the payload from the Byron address + let payload_bytes = byron_addr.to_vec(); + Ok(payload_bytes.as_data()) + } + _ => Err(super::Error::CoerceError( + "Address type does not support payment parts".to_string(), + "Payment credential".to_string(), + )), + } +} + +fn address_staking_part(data: &HashMap) -> Result { + let addr = extract_address(data)?; + + match addr { + addresses::Address::Shelley(shelley_addr) => { + Ok(shelley_addr.delegation().to_vec().as_data()) + } + addresses::Address::Stake(stake_addr) => { + Ok(stake_addr.to_vec().as_data()) + } + _ => Err(super::Error::CoerceError( + "Address type does not support staking parts".to_string(), + "Staking credential".to_string(), + )), + } } \ No newline at end of file diff --git a/examples/reference_script.publish_native.tir b/examples/reference_script.publish_native.tir index 6c2349db..1f3904d1 100644 --- a/examples/reference_script.publish_native.tir +++ b/examples/reference_script.publish_native.tir @@ -136,9 +136,6 @@ { "name": "cardano_publish", "data": { - "version": { - "Number": 0 - }, "script": { "Bytes": [ 130, @@ -157,6 +154,9 @@ ] } }, + "version": { + "Number": 0 + }, "amount": { "Assets": [ { diff --git a/examples/reference_script.publish_plutus.tir b/examples/reference_script.publish_plutus.tir index 70e3979c..79d56066 100644 --- a/examples/reference_script.publish_plutus.tir +++ b/examples/reference_script.publish_plutus.tir @@ -136,6 +136,14 @@ { "name": "cardano_publish", "data": { + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, "amount": { "Assets": [ { @@ -155,14 +163,6 @@ "version": { "Number": 3 }, - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } - }, "script": { "Bytes": [ 81, diff --git a/examples/withdrawal.transfer.tir b/examples/withdrawal.transfer.tir index fb2ac831..41c277bf 100644 --- a/examples/withdrawal.transfer.tir +++ b/examples/withdrawal.transfer.tir @@ -163,6 +163,14 @@ { "name": "withdrawal", "data": { + "credential": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, "redeemer": { "Struct": { "constructor": 0, @@ -171,14 +179,6 @@ }, "amount": { "Number": 0 - }, - "credential": { - "EvalParam": { - "ExpectValue": [ - "sender", - "Address" - ] - } } } } From ab56b75aa6af6987a516c4fc3cb93ec61adcfef6 Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Thu, 16 Oct 2025 18:00:11 -0300 Subject: [PATCH 6/7] examples fixes --- crates/tx3-lang/src/parsing.rs | 6 +- examples/lang_tour.ast | 898 ++++++++++++++----- examples/lang_tour.my_tx.tir | 191 +++- examples/party_serialization.ast | 1 + examples/reference_script.publish_native.tir | 16 +- examples/reference_script.publish_plutus.tir | 36 +- examples/withdrawal.transfer.tir | 3 - 7 files changed, 874 insertions(+), 277 deletions(-) diff --git a/crates/tx3-lang/src/parsing.rs b/crates/tx3-lang/src/parsing.rs index 1866848d..1436f4d4 100644 --- a/crates/tx3-lang/src/parsing.rs +++ b/crates/tx3-lang/src/parsing.rs @@ -2722,11 +2722,11 @@ mod tests { #[test] fn test_spans_are_respected() { let program = parse_well_known_example("lang_tour"); - assert_eq!(program.span, Span::new(0, 1560)); + assert_eq!(program.span, Span::new(0, 2370)); - assert_eq!(program.parties[0].span, Span::new(47, 61)); + assert_eq!(program.parties[0].span, Span::new(92, 106)); - assert_eq!(program.types[0].span, Span::new(63, 158)); + assert_eq!(program.types[0].span, Span::new(108, 232)); } fn make_snapshot_if_missing(example: &str, program: &Program) { diff --git a/examples/lang_tour.ast b/examples/lang_tour.ast index 812c24be..79807a27 100644 --- a/examples/lang_tour.ast +++ b/examples/lang_tour.ast @@ -18,12 +18,32 @@ "start": 28, "end": 42 } + }, + { + "name": "field_c", + "type": "Bool", + "span": { + "dummy": false, + "start": 48, + "end": 61 + } + }, + { + "name": "field_d", + "type": { + "List": "Bytes" + }, + "span": { + "dummy": false, + "start": 67, + "end": 87 + } } ], "span": { "dummy": false, "start": 0, - "end": 45 + "end": 90 } }, "txs": [ @@ -32,8 +52,8 @@ "value": "my_tx", "span": { "dummy": false, - "start": 466, - "end": 471 + "start": 540, + "end": 545 } }, "parameters": { @@ -43,8 +63,8 @@ "value": "quantity", "span": { "dummy": false, - "start": 477, - "end": 485 + "start": 551, + "end": 559 } }, "type": "Int" @@ -54,8 +74,8 @@ "value": "validUntil", "span": { "dummy": false, - "start": 496, - "end": 506 + "start": 570, + "end": 580 } }, "type": "Int" @@ -65,8 +85,8 @@ "value": "metadata", "span": { "dummy": false, - "start": 517, - "end": 525 + "start": 591, + "end": 599 } }, "type": "Bytes" @@ -74,12 +94,88 @@ ], "span": { "dummy": false, - "start": 471, - "end": 535 + "start": 545, + "end": 609 + } + }, + "locals": { + "assigns": [ + { + "name": { + "value": "local_var", + "span": { + "dummy": false, + "start": 1914, + "end": 1923 + } + }, + "value": { + "ConcatOp": { + "lhs": { + "String": { + "value": "Lang", + "span": { + "dummy": false, + "start": 1932, + "end": 1938 + } + } + }, + "rhs": { + "String": { + "value": "Tour", + "span": { + "dummy": false, + "start": 1940, + "end": 1946 + } + } + }, + "span": { + "dummy": false, + "start": 1925, + "end": 1947 + } + } + }, + "span": { + "dummy": false, + "start": 1914, + "end": 1947 + } + } + ], + "span": { + "dummy": false, + "start": 1897, + "end": 1954 } }, - "locals": null, - "references": [], + "references": [ + { + "name": "ref_block", + "ref": { + "UtxoRef": { + "txid": [ + 171, + 205, + 239 + ], + "index": 2, + "span": { + "dummy": false, + "start": 1220, + "end": 1230 + } + } + }, + "span": { + "dummy": false, + "start": 1185, + "end": 1237 + } + } + ], "inputs": [ { "name": "source", @@ -91,8 +187,8 @@ "value": "MyParty", "span": { "dummy": false, - "start": 571, - "end": 578 + "start": 645, + "end": 652 } } } @@ -118,8 +214,8 @@ "value": "Ada", "span": { "dummy": false, - "start": 628, - "end": 631 + "start": 702, + "end": 705 } }, "amount": { @@ -127,15 +223,15 @@ "value": "quantity", "span": { "dummy": false, - "start": 632, - "end": 640 + "start": 706, + "end": 714 } } }, "span": { "dummy": false, - "start": 628, - "end": 641 + "start": 702, + "end": 715 } } }, @@ -144,15 +240,15 @@ "value": "named_output", "span": { "dummy": false, - "start": 653, - "end": 665 + "start": 727, + "end": 739 } } }, "span": { "dummy": false, - "start": 642, - "end": 643 + "start": 716, + "end": 717 } } } @@ -164,8 +260,8 @@ "value": "MyVariant", "span": { "dummy": false, - "start": 686, - "end": 695 + "start": 760, + "end": 769 } }, "case": { @@ -173,8 +269,8 @@ "value": "Case1", "span": { "dummy": false, - "start": 697, - "end": 702 + "start": 771, + "end": 776 } }, "fields": [ @@ -183,8 +279,8 @@ "value": "field1", "span": { "dummy": false, - "start": 717, - "end": 723 + "start": 791, + "end": 797 } }, "value": { @@ -192,15 +288,15 @@ "value": "field_a", "span": { "dummy": false, - "start": 725, - "end": 732 + "start": 799, + "end": 806 } } }, "span": { "dummy": false, - "start": 717, - "end": 732 + "start": 791, + "end": 806 } }, { @@ -208,8 +304,8 @@ "value": "field2", "span": { "dummy": false, - "start": 746, - "end": 752 + "start": 820, + "end": 826 } }, "value": { @@ -217,15 +313,15 @@ "value": "AFAFAF", "span": { "dummy": false, - "start": 754, - "end": 762 + "start": 828, + "end": 836 } } }, "span": { "dummy": false, - "start": 746, - "end": 762 + "start": 820, + "end": 836 } }, { @@ -233,8 +329,8 @@ "value": "field3", "span": { "dummy": false, - "start": 776, - "end": 782 + "start": 850, + "end": 856 } }, "value": { @@ -242,29 +338,29 @@ "value": "quantity", "span": { "dummy": false, - "start": 784, - "end": 792 + "start": 858, + "end": 866 } } }, "span": { "dummy": false, - "start": 776, - "end": 792 + "start": 850, + "end": 866 } } ], "spread": null, "span": { "dummy": false, - "start": 695, - "end": 803 + "start": 769, + "end": 877 } }, "span": { "dummy": false, - "start": 686, - "end": 803 + "start": 760, + "end": 877 } } } @@ -272,8 +368,8 @@ ], "span": { "dummy": false, - "start": 542, - "end": 810 + "start": 616, + "end": 884 } } ], @@ -283,8 +379,8 @@ "value": "named_output", "span": { "dummy": false, - "start": 996, - "end": 1008 + "start": 1250, + "end": 1262 } }, "fields": [ @@ -294,8 +390,8 @@ "value": "MyParty", "span": { "dummy": false, - "start": 1023, - "end": 1030 + "start": 1277, + "end": 1284 } } } @@ -307,8 +403,8 @@ "value": "MyRecord", "span": { "dummy": false, - "start": 1047, - "end": 1055 + "start": 1301, + "end": 1309 } }, "case": { @@ -326,8 +422,8 @@ "value": "field1", "span": { "dummy": false, - "start": 1070, - "end": 1076 + "start": 1324, + "end": 1330 } }, "value": { @@ -335,15 +431,15 @@ "value": "quantity", "span": { "dummy": false, - "start": 1078, - "end": 1086 + "start": 1332, + "end": 1340 } } }, "span": { "dummy": false, - "start": 1070, - "end": 1086 + "start": 1324, + "end": 1340 } }, { @@ -351,8 +447,8 @@ "value": "field2", "span": { "dummy": false, - "start": 1100, - "end": 1106 + "start": 1354, + "end": 1360 } }, "value": { @@ -367,8 +463,8 @@ }, "span": { "dummy": false, - "start": 1112, - "end": 1113 + "start": 1366, + "end": 1367 } } }, @@ -382,22 +478,22 @@ }, "span": { "dummy": false, - "start": 1123, - "end": 1124 + "start": 1377, + "end": 1378 } } }, "span": { "dummy": false, - "start": 1118, - "end": 1119 + "start": 1372, + "end": 1373 } } }, "span": { "dummy": false, - "start": 1100, - "end": 1127 + "start": 1354, + "end": 1381 } }, { @@ -405,8 +501,8 @@ "value": "field4", "span": { "dummy": false, - "start": 1141, - "end": 1147 + "start": 1395, + "end": 1401 } }, "value": { @@ -428,8 +524,8 @@ "value": "source", "span": { "dummy": false, - "start": 1159, - "end": 1165 + "start": 1413, + "end": 1419 } } }, @@ -438,30 +534,96 @@ "value": "field1", "span": { "dummy": false, - "start": 1166, - "end": 1172 + "start": 1420, + "end": 1426 } } }, "span": { "dummy": false, - "start": 1165, - "end": 1172 + "start": 1419, + "end": 1426 + } + } + } + ], + "span": { + "dummy": false, + "start": 1403, + "end": 1427 + } + } + }, + "span": { + "dummy": false, + "start": 1395, + "end": 1427 + } + }, + { + "name": { + "value": "field5", + "span": { + "dummy": false, + "start": 1441, + "end": 1447 + } + }, + "value": { + "MapConstructor": { + "fields": [ + { + "key": { + "Number": 1 + }, + "value": { + "String": { + "value": "Value1", + "span": { + "dummy": false, + "start": 1453, + "end": 1461 + } } + }, + "span": { + "dummy": false, + "start": 1450, + "end": 1461 + } + }, + { + "key": { + "Number": 2 + }, + "value": { + "String": { + "value": "Value2", + "span": { + "dummy": false, + "start": 1466, + "end": 1474 + } + } + }, + "span": { + "dummy": false, + "start": 1463, + "end": 1474 } } ], "span": { "dummy": false, - "start": 1149, - "end": 1173 + "start": 1449, + "end": 1476 } } }, "span": { "dummy": false, - "start": 1141, - "end": 1173 + "start": 1441, + "end": 1476 } } ], @@ -470,21 +632,21 @@ "value": "source", "span": { "dummy": false, - "start": 1190, - "end": 1196 + "start": 1493, + "end": 1499 } } }, "span": { "dummy": false, - "start": 1056, - "end": 1206 + "start": 1310, + "end": 1509 } }, "span": { "dummy": false, - "start": 1047, - "end": 1206 + "start": 1301, + "end": 1509 } } } @@ -503,8 +665,8 @@ "value": "source", "span": { "dummy": false, - "start": 1233, - "end": 1239 + "start": 1536, + "end": 1542 } } }, @@ -513,15 +675,15 @@ "value": "field3", "span": { "dummy": false, - "start": 1240, - "end": 1246 + "start": 1543, + "end": 1549 } } }, "span": { "dummy": false, - "start": 1239, - "end": 1246 + "start": 1542, + "end": 1549 } } }, @@ -532,8 +694,8 @@ "value": "source", "span": { "dummy": false, - "start": 1248, - "end": 1254 + "start": 1551, + "end": 1557 } } }, @@ -542,15 +704,15 @@ "value": "field2", "span": { "dummy": false, - "start": 1255, - "end": 1261 + "start": 1558, + "end": 1564 } } }, "span": { "dummy": false, - "start": 1254, - "end": 1261 + "start": 1557, + "end": 1564 } } }, @@ -561,8 +723,8 @@ "value": "source", "span": { "dummy": false, - "start": 1263, - "end": 1269 + "start": 1566, + "end": 1572 } } }, @@ -571,22 +733,22 @@ "value": "field1", "span": { "dummy": false, - "start": 1270, - "end": 1276 + "start": 1573, + "end": 1579 } } }, "span": { "dummy": false, - "start": 1269, - "end": 1276 + "start": 1572, + "end": 1579 } } }, "span": { "dummy": false, - "start": 1224, - "end": 1277 + "start": 1527, + "end": 1580 } } }, @@ -596,8 +758,8 @@ "value": "Ada", "span": { "dummy": false, - "start": 1280, - "end": 1283 + "start": 1583, + "end": 1586 } }, "amount": { @@ -605,15 +767,15 @@ }, "span": { "dummy": false, - "start": 1280, - "end": 1287 + "start": 1583, + "end": 1590 } } }, "span": { "dummy": false, - "start": 1278, - "end": 1279 + "start": 1581, + "end": 1582 } } }, @@ -622,15 +784,15 @@ "value": "named_output", "span": { "dummy": false, - "start": 1299, - "end": 1311 + "start": 1602, + "end": 1614 } } }, "span": { "dummy": false, - "start": 1288, - "end": 1289 + "start": 1591, + "end": 1592 } } } @@ -638,17 +800,15 @@ ], "span": { "dummy": false, - "start": 989, - "end": 1319 + "start": 1243, + "end": 1622 } } ], "validity": { "fields": [ { - "SinceSlot": { - "Number": 1735700400000 - } + "SinceSlot": "ComputeTipSlot" }, { "UntilSlot": { @@ -656,8 +816,8 @@ "value": "validUntil", "span": { "dummy": false, - "start": 1497, - "end": 1507 + "start": 1797, + "end": 1807 } } } @@ -665,8 +825,8 @@ ], "span": { "dummy": false, - "start": 1431, - "end": 1514 + "start": 1734, + "end": 1814 } }, "mints": [ @@ -679,8 +839,8 @@ "value": "StaticAsset", "span": { "dummy": false, - "start": 839, - "end": 850 + "start": 913, + "end": 924 } }, "amount": { @@ -688,8 +848,8 @@ }, "span": { "dummy": false, - "start": 839, - "end": 855 + "start": 913, + "end": 929 } } } @@ -700,8 +860,8 @@ ], "span": { "dummy": false, - "start": 816, - "end": 884 + "start": 890, + "end": 958 } }, { @@ -714,8 +874,8 @@ "value": "AB11223344", "span": { "dummy": false, - "start": 922, - "end": 934 + "start": 996, + "end": 1008 } } }, @@ -724,8 +884,8 @@ "value": "OTHER_TOKEN", "span": { "dummy": false, - "start": 936, - "end": 949 + "start": 1010, + "end": 1023 } } }, @@ -734,8 +894,8 @@ }, "span": { "dummy": false, - "start": 913, - "end": 954 + "start": 987, + "end": 1028 } } } @@ -746,12 +906,47 @@ ], "span": { "dummy": false, - "start": 890, - "end": 983 + "start": 964, + "end": 1057 + } + } + ], + "burns": [ + { + "fields": [ + { + "Amount": { + "StaticAssetConstructor": { + "type": { + "value": "StaticAsset", + "span": { + "dummy": false, + "start": 1086, + "end": 1097 + } + }, + "amount": { + "Number": 50 + }, + "span": { + "dummy": false, + "start": 1086, + "end": 1101 + } + } + } + }, + { + "Redeemer": "Unit" + } + ], + "span": { + "dummy": false, + "start": 1063, + "end": 1130 } } ], - "burns": [], "signers": { "signers": [ { @@ -759,8 +954,8 @@ "value": "MyParty", "span": { "dummy": false, - "start": 1343, - "end": 1350 + "start": 1646, + "end": 1653 } } }, @@ -769,25 +964,207 @@ "value": "0F5B22E57FEEB5B4FD1D501B007A427C56A76884D4978FAFEF979D9C", "span": { "dummy": false, - "start": 1360, - "end": 1418 + "start": 1663, + "end": 1721 } } } ], "span": { "dummy": false, - "start": 1325, - "end": 1425 + "start": 1628, + "end": 1728 } }, - "adhoc": [], + "adhoc": [ + { + "Cardano": { + "VoteDelegationCertificate": { + "drep": { + "HexString": { + "value": "12345678", + "span": { + "dummy": false, + "start": 2013, + "end": 2023 + } + } + }, + "stake": { + "HexString": { + "value": "87654321", + "span": { + "dummy": false, + "start": 2040, + "end": 2050 + } + } + }, + "span": { + "dummy": false, + "start": 1969, + "end": 2057 + } + } + } + }, + { + "Cardano": { + "Withdrawal": { + "fields": [ + { + "From": { + "Identifier": { + "value": "MyParty", + "span": { + "dummy": false, + "start": 2099, + "end": 2106 + } + } + } + }, + { + "Amount": { + "Number": 100 + } + }, + { + "Redeemer": "Unit" + } + ], + "span": { + "dummy": false, + "start": 2072, + "end": 2156 + } + } + } + }, + { + "Cardano": { + "PlutusWitness": { + "fields": [ + { + "Version": [ + { + "Number": 2 + }, + { + "dummy": false, + "start": 2196, + "end": 2206 + } + ] + }, + { + "Script": [ + { + "HexString": { + "value": "ABCDEF1234", + "span": { + "dummy": false, + "start": 2224, + "end": 2236 + } + } + }, + { + "dummy": false, + "start": 2216, + "end": 2236 + } + ] + } + ], + "span": { + "dummy": false, + "start": 2171, + "end": 2243 + } + } + } + }, + { + "Cardano": { + "NativeWitness": { + "fields": [ + { + "Script": [ + { + "HexString": { + "value": "12345678", + "span": { + "dummy": false, + "start": 2291, + "end": 2301 + } + } + }, + { + "dummy": false, + "start": 2283, + "end": 2301 + } + ] + } + ], + "span": { + "dummy": false, + "start": 2258, + "end": 2308 + } + } + } + }, + { + "Cardano": { + "TreasuryDonation": { + "coin": { + "Number": 500 + }, + "span": { + "dummy": false, + "start": 2323, + "end": 2367 + } + } + } + } + ], "span": { "dummy": false, - "start": 463, - "end": 1559 + "start": 537, + "end": 2369 }, - "collateral": [], + "collateral": [ + { + "fields": [ + { + "Ref": { + "UtxoRef": { + "txid": [ + 171, + 205, + 239 + ], + "index": 1, + "span": { + "dummy": false, + "start": 1162, + "end": 1172 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 1136, + "end": 1179 + } + } + ], "metadata": { "fields": [ { @@ -799,22 +1176,42 @@ "value": "metadata", "span": { "dummy": false, - "start": 1542, - "end": 1550 + "start": 1842, + "end": 1850 } } }, "span": { "dummy": false, - "start": 1539, - "end": 1550 + "start": 1839, + "end": 1850 + } + }, + { + "key": { + "Number": 2 + }, + "value": { + "String": { + "value": "Additional Metadata", + "span": { + "dummy": false, + "start": 1863, + "end": 1884 + } + } + }, + "span": { + "dummy": false, + "start": 1860, + "end": 1884 } } ], "span": { "dummy": false, - "start": 1520, - "end": 1557 + "start": 1820, + "end": 1891 } } } @@ -825,8 +1222,8 @@ "value": "MyRecord", "span": { "dummy": false, - "start": 68, - "end": 76 + "start": 113, + "end": 121 } }, "cases": [ @@ -845,15 +1242,15 @@ "value": "field1", "span": { "dummy": false, - "start": 83, - "end": 89 + "start": 128, + "end": 134 } }, "type": "Int", "span": { "dummy": false, - "start": 83, - "end": 94 + "start": 128, + "end": 139 } }, { @@ -861,15 +1258,15 @@ "value": "field2", "span": { "dummy": false, - "start": 100, - "end": 106 + "start": 145, + "end": 151 } }, "type": "Bytes", "span": { "dummy": false, - "start": 100, - "end": 113 + "start": 145, + "end": 158 } }, { @@ -877,15 +1274,15 @@ "value": "field3", "span": { "dummy": false, - "start": 119, - "end": 125 + "start": 164, + "end": 170 } }, "type": "Bytes", "span": { "dummy": false, - "start": 119, - "end": 132 + "start": 164, + "end": 177 } }, { @@ -893,8 +1290,8 @@ "value": "field4", "span": { "dummy": false, - "start": 138, - "end": 144 + "start": 183, + "end": 189 } }, "type": { @@ -902,22 +1299,43 @@ }, "span": { "dummy": false, - "start": 138, - "end": 155 + "start": 183, + "end": 200 + } + }, + { + "name": { + "value": "field5", + "span": { + "dummy": false, + "start": 206, + "end": 212 + } + }, + "type": { + "Map": [ + "Int", + "Bytes" + ] + }, + "span": { + "dummy": false, + "start": 206, + "end": 229 } } ], "span": { "dummy": false, - "start": 63, - "end": 158 + "start": 108, + "end": 232 } } ], "span": { "dummy": false, - "start": 63, - "end": 158 + "start": 108, + "end": 232 } }, { @@ -925,8 +1343,8 @@ "value": "MyVariant", "span": { "dummy": false, - "start": 165, - "end": 174 + "start": 239, + "end": 248 } }, "cases": [ @@ -935,8 +1353,8 @@ "value": "Case1", "span": { "dummy": false, - "start": 181, - "end": 186 + "start": 255, + "end": 260 } }, "fields": [ @@ -945,15 +1363,15 @@ "value": "field1", "span": { "dummy": false, - "start": 197, - "end": 203 + "start": 271, + "end": 277 } }, "type": "Int", "span": { "dummy": false, - "start": 197, - "end": 208 + "start": 271, + "end": 282 } }, { @@ -961,15 +1379,15 @@ "value": "field2", "span": { "dummy": false, - "start": 218, - "end": 224 + "start": 292, + "end": 298 } }, "type": "Bytes", "span": { "dummy": false, - "start": 218, - "end": 231 + "start": 292, + "end": 305 } }, { @@ -977,22 +1395,22 @@ "value": "field3", "span": { "dummy": false, - "start": 241, - "end": 247 + "start": 315, + "end": 321 } }, "type": "Int", "span": { "dummy": false, - "start": 241, - "end": 252 + "start": 315, + "end": 326 } } ], "span": { "dummy": false, - "start": 181, - "end": 259 + "start": 255, + "end": 333 } }, { @@ -1000,22 +1418,22 @@ "value": "Case2", "span": { "dummy": false, - "start": 265, - "end": 270 + "start": 339, + "end": 344 } }, "fields": [], "span": { "dummy": false, - "start": 265, - "end": 270 + "start": 339, + "end": 344 } } ], "span": { "dummy": false, - "start": 160, - "end": 273 + "start": 234, + "end": 347 } } ], @@ -1026,8 +1444,8 @@ "value": "StaticAsset", "span": { "dummy": false, - "start": 320, - "end": 331 + "start": 394, + "end": 405 } }, "policy": { @@ -1035,8 +1453,8 @@ "value": "ABCDEF1234", "span": { "dummy": false, - "start": 334, - "end": 346 + "start": 408, + "end": 420 } } }, @@ -1045,15 +1463,15 @@ "value": "MYTOKEN", "span": { "dummy": false, - "start": 347, - "end": 356 + "start": 421, + "end": 430 } } }, "span": { "dummy": false, - "start": 314, - "end": 357 + "start": 388, + "end": 431 } } ], @@ -1063,14 +1481,14 @@ "value": "MyParty", "span": { "dummy": false, - "start": 53, - "end": 60 + "start": 98, + "end": 105 } }, "span": { "dummy": false, - "start": 47, - "end": 61 + "start": 92, + "end": 106 } } ], @@ -1080,8 +1498,8 @@ "value": "OnlyHashPolicy", "span": { "dummy": false, - "start": 282, - "end": 296 + "start": 356, + "end": 370 } }, "value": { @@ -1089,15 +1507,15 @@ "value": "ABCDEF1234", "span": { "dummy": false, - "start": 299, - "end": 311 + "start": 373, + "end": 385 } } }, "span": { "dummy": false, - "start": 275, - "end": 312 + "start": 349, + "end": 386 } }, { @@ -1105,8 +1523,8 @@ "value": "FullyDefinedPolicy", "span": { "dummy": false, - "start": 366, - "end": 384 + "start": 440, + "end": 458 } }, "value": { @@ -1118,8 +1536,8 @@ "value": "ABCDEF1234", "span": { "dummy": false, - "start": 397, - "end": 409 + "start": 471, + "end": 483 } } } @@ -1130,8 +1548,8 @@ "value": "ABCDEF1234", "span": { "dummy": false, - "start": 423, - "end": 435 + "start": 497, + "end": 509 } } } @@ -1142,8 +1560,8 @@ "value": "ABCDEF1234", "span": { "dummy": false, - "start": 446, - "end": 458 + "start": 520, + "end": 532 } } } @@ -1151,21 +1569,21 @@ ], "span": { "dummy": false, - "start": 385, - "end": 461 + "start": 459, + "end": 535 } } }, "span": { "dummy": false, - "start": 359, - "end": 461 + "start": 433, + "end": 535 } } ], "span": { "dummy": false, "start": 0, - "end": 1560 + "end": 2370 } } \ No newline at end of file diff --git a/examples/lang_tour.my_tx.tir b/examples/lang_tour.my_tx.tir index c1ed8b7e..efe7be77 100644 --- a/examples/lang_tour.my_tx.tir +++ b/examples/lang_tour.my_tx.tir @@ -2,7 +2,20 @@ "fees": { "EvalParam": "ExpectFees" }, - "references": [], + "references": [ + { + "UtxoRefs": [ + { + "txid": [ + 171, + 205, + 239 + ], + "index": 2 + } + ] + } + ], "inputs": [ { "name": "source", @@ -275,6 +288,26 @@ } } ] + }, + { + "Map": [ + [ + { + "Number": 1 + }, + { + "String": "Value1" + } + ], + [ + { + "Number": 2 + }, + { + "String": "Value2" + } + ] + ] } ] } @@ -505,7 +538,7 @@ ], "validity": { "since": { - "Number": 1735700400000 + "EvalCompiler": "ComputeTipSlot" }, "until": { "EvalParam": { @@ -576,9 +609,149 @@ } } ], - "burns": [], - "adhoc": [], - "collateral": [], + "burns": [ + { + "amount": { + "Assets": [ + { + "policy": { + "Bytes": [ + 171, + 205, + 239, + 18, + 52 + ] + }, + "asset_name": { + "String": "MYTOKEN" + }, + "amount": { + "Number": 50 + } + } + ] + }, + "redeemer": { + "Struct": { + "constructor": 0, + "fields": [] + } + } + } + ], + "adhoc": [ + { + "name": "vote_delegation_certificate", + "data": { + "drep": { + "Bytes": [ + 18, + 52, + 86, + 120 + ] + }, + "stake": { + "Bytes": [ + 135, + 101, + 67, + 33 + ] + } + } + }, + { + "name": "withdrawal", + "data": { + "credential": { + "EvalParam": { + "ExpectValue": [ + "myparty", + "Address" + ] + } + }, + "amount": { + "Number": 100 + }, + "redeemer": { + "Struct": { + "constructor": 0, + "fields": [] + } + } + } + }, + { + "name": "plutus_witness", + "data": { + "version": { + "Number": 2 + }, + "script": { + "Bytes": [ + 171, + 205, + 239, + 18, + 52 + ] + } + } + }, + { + "name": "native_witness", + "data": { + "script": { + "Bytes": [ + 18, + 52, + 86, + 120 + ] + } + } + }, + { + "name": "treasury_donation", + "data": { + "coin": { + "Number": 500 + } + } + } + ], + "collateral": [ + { + "utxos": { + "EvalParam": { + "ExpectInput": [ + "collateral", + { + "address": "None", + "min_amount": "None", + "ref": { + "UtxoRefs": [ + { + "txid": [ + 171, + 205, + 239 + ], + "index": 1 + } + ] + }, + "many": false, + "collateral": true + } + ] + } + } + } + ], "signers": { "signers": [ { @@ -636,6 +809,14 @@ ] } } + }, + { + "key": { + "Number": 2 + }, + "value": { + "String": "Additional Metadata" + } } ] } \ No newline at end of file diff --git a/examples/party_serialization.ast b/examples/party_serialization.ast index a86a1fc1..08731cf2 100644 --- a/examples/party_serialization.ast +++ b/examples/party_serialization.ast @@ -365,6 +365,7 @@ } } ], + "aliases": [], "assets": [], "parties": [ { diff --git a/examples/reference_script.publish_native.tir b/examples/reference_script.publish_native.tir index 9cf434b9..12ece215 100644 --- a/examples/reference_script.publish_native.tir +++ b/examples/reference_script.publish_native.tir @@ -136,6 +136,14 @@ { "name": "cardano_publish", "data": { + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, "amount": { "Assets": [ { @@ -152,14 +160,6 @@ } ] }, - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } - }, "version": { "Number": 0 }, diff --git a/examples/reference_script.publish_plutus.tir b/examples/reference_script.publish_plutus.tir index 053b3279..fab2edf1 100644 --- a/examples/reference_script.publish_plutus.tir +++ b/examples/reference_script.publish_plutus.tir @@ -136,6 +136,9 @@ { "name": "cardano_publish", "data": { + "version": { + "Number": 3 + }, "to": { "EvalParam": { "ExpectValue": [ @@ -144,8 +147,21 @@ ] } }, - "version": { - "Number": 3 + "amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] }, "script": { "Bytes": [ @@ -168,22 +184,6 @@ 174, 105 ] - }, - "amount": { - "Assets": [ - { - "policy": "None", - "asset_name": "None", - "amount": { - "EvalParam": { - "ExpectValue": [ - "quantity", - "Int" - ] - } - } - } - ] } } } diff --git a/examples/withdrawal.transfer.tir b/examples/withdrawal.transfer.tir index 54f76d64..5130bab6 100644 --- a/examples/withdrawal.transfer.tir +++ b/examples/withdrawal.transfer.tir @@ -179,9 +179,6 @@ "constructor": 0, "fields": [] } - }, - "amount": { - "Number": 0 } } } From c8bf7321fc97a553e39ab89ce6074c7a732776c7 Mon Sep 17 00:00:00 2001 From: Benjamin Martinez Picech Date: Thu, 16 Oct 2025 18:02:19 -0300 Subject: [PATCH 7/7] simplification of payment extraction --- crates/tx3-cardano/src/compile/plutus_data.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/tx3-cardano/src/compile/plutus_data.rs b/crates/tx3-cardano/src/compile/plutus_data.rs index 0d804b59..fa320487 100644 --- a/crates/tx3-cardano/src/compile/plutus_data.rs +++ b/crates/tx3-cardano/src/compile/plutus_data.rs @@ -188,14 +188,10 @@ fn address_payment_part(data: &HashMap) -> Result { - // Extract the payment credential from the Shelley address - let payment_bytes = shelley_addr.payment().to_vec(); - Ok(payment_bytes.as_data()) + Ok(shelley_addr.payment().to_vec().as_data()) } addresses::Address::Byron(byron_addr) => { - // Extract the payload from the Byron address - let payload_bytes = byron_addr.to_vec(); - Ok(payload_bytes.as_data()) + Ok(byron_addr.to_vec().as_data()) } _ => Err(super::Error::CoerceError( "Address type does not support payment parts".to_string(),