Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions crates/tx3-cardano/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,24 +288,38 @@ fn compile_outputs(
tx: &tir::Tx,
network: Network,
) -> Result<Vec<primitives::TransactionOutput<'static>>, Error> {
let mut resolved: Vec<_> = tx
.outputs
.iter()
.map(|out| (out.optional, compile_output_block(out, network)))
.filter(|(optional, output)| !optional || output_has_assets(output))
.map(|(_, output)| output)
.collect::<Result<Vec<_>, _>>()?;
let outputs = tx.outputs.iter().filter_map(|out| {
let compiled = compile_output_block(out, network);

if out.optional && !output_has_assets(&compiled) {
return None;
}

let idx = out.declared_index.as_number().map(|n| n as usize);
Some(compiled.map(|o| (idx, o)))
});

let cardano_outputs = tx
.adhoc
.iter()
.filter(|x| x.name.as_str() == "cardano_publish")
.map(|adhoc| compile_cardano_publish_directive(adhoc, network))
.map(|adhoc| {
let idx = adhoc
.data
.get("declared_index")
.and_then(|expr| expr.as_number())
.map(|n| n as usize);

compile_cardano_publish_directive(adhoc, network).map(|o| (idx, o))
});

let mut all_outputs: Vec<_> = outputs
.chain(cardano_outputs)
.collect::<Result<Vec<_>, _>>()?;

resolved.extend(cardano_outputs);
all_outputs.sort_by_key(|(idx, _)| idx.unwrap_or(usize::MAX));

Ok(resolved)
Ok(all_outputs.into_iter().map(|(_, out)| out).collect())
}

pub fn compile_cardano_publish_directive(
Expand Down
20 changes: 20 additions & 0 deletions crates/tx3-cardano/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,23 @@ async fn min_utxo_compiler_op_test() {
assert!(!assets.is_empty());
}
}

#[pollster::test]
async fn cardano_publish_min_utxo_test() {
let mut compiler = test_compiler(None);
let utxos = wildcard_utxos(None);
let protocol = load_protocol("cardano_publish_min_utxo");

let tx = protocol.tir("test_min_utxo_publish").unwrap().clone();

let args = BTreeMap::from([]);

let tx = test_compile(tx, &args, &mut compiler, utxos);

println!("{}", hex::encode(tx.payload));

assert_eq!(
hex::encode(tx.hash),
"2da0a42d6245f61d595f0acf77df1560fd3e4c5f553737caf606003804ea5014"
);
}
17 changes: 15 additions & 2 deletions crates/tx3-lang/src/analyzing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,8 +1243,21 @@ impl TxDef {
scope.track_input(&input.name, input.clone())
}

for (index, output) in self.outputs.iter().enumerate() {
scope.track_output(index, output.clone())
for output in self.outputs.iter() {
scope.track_output(output.declared_index, output.clone())
}

for adhoc in self.adhoc.iter() {
match adhoc {
ChainSpecificBlock::Cardano(crate::cardano::CardanoBlock::Publish(pb)) => {
if let Some(n) = &pb.name {
scope
.symbols
.insert(n.value.clone(), Symbol::Output(pb.declared_index));
}
}
_ => {}
}
}

let scope_snapshot = Rc::new(scope);
Expand Down
1 change: 1 addition & 0 deletions crates/tx3-lang/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ pub struct OutputBlock {
pub optional: bool,
pub fields: Vec<OutputBlockField>,
pub span: Span,
pub declared_index: usize,
}

impl OutputBlock {
Expand Down
32 changes: 27 additions & 5 deletions crates/tx3-lang/src/cardano.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ pub struct CardanoPublishBlock {
pub name: Option<Identifier>,
pub fields: Vec<CardanoPublishBlockField>,
pub span: Span,
pub declared_index: usize,
}

impl CardanoPublishBlock {
Expand Down Expand Up @@ -663,7 +664,12 @@ impl AstNode for CardanoPublishBlock {
.map(|x| CardanoPublishBlockField::parse(x))
.collect::<Result<Vec<_>, _>>()?;

Ok(CardanoPublishBlock { name, fields, span })
Ok(CardanoPublishBlock {
name,
fields,
span,
declared_index: 0,
})
}

fn span(&self) -> &Span {
Expand Down Expand Up @@ -711,9 +717,18 @@ impl IntoLower for CardanoPublishBlockField {
ctx: &crate::lowering::Context,
) -> Result<Self::Output, crate::lowering::Error> {
match self {
CardanoPublishBlockField::To(x) => Ok(("to".to_string(), x.into_lower(ctx)?)),
CardanoPublishBlockField::Amount(x) => Ok(("amount".to_string(), x.into_lower(ctx)?)),
CardanoPublishBlockField::Datum(x) => Ok(("datum".to_string(), x.into_lower(ctx)?)),
CardanoPublishBlockField::To(x) => {
let ctx = ctx.enter_address_expr();
Ok(("to".to_string(), x.into_lower(&ctx)?))
}
CardanoPublishBlockField::Amount(x) => {
let ctx = ctx.enter_asset_expr();
Ok(("amount".to_string(), x.into_lower(&ctx)?))
}
CardanoPublishBlockField::Datum(x) => {
let ctx = ctx.enter_datum_expr();
Ok(("datum".to_string(), x.into_lower(&ctx)?))
}
CardanoPublishBlockField::Version(x) => Ok(("version".to_string(), x.into_lower(ctx)?)),
CardanoPublishBlockField::Script(x) => Ok(("script".to_string(), x.into_lower(ctx)?)),
}
Expand All @@ -727,12 +742,17 @@ impl IntoLower for CardanoPublishBlock {
&self,
ctx: &crate::lowering::Context,
) -> Result<Self::Output, crate::lowering::Error> {
let data = self
let mut data: HashMap<String, ir::Expression> = self
.fields
.iter()
.map(|x| x.into_lower(ctx))
.collect::<Result<_, _>>()?;

data.insert(
"declared_index".to_string(),
ir::Expression::Number(self.declared_index as i128),
);

Ok(ir::AdHocDirective {
name: "cardano_publish".to_string(),
data,
Expand Down Expand Up @@ -938,6 +958,7 @@ mod tests {
))),
],
span: Span::DUMMY,
declared_index: 0,
}
);

Expand Down Expand Up @@ -967,6 +988,7 @@ mod tests {
))),
],
span: Span::DUMMY,
declared_index: 0,
}
);

Expand Down
2 changes: 2 additions & 0 deletions crates/tx3-lang/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,12 +697,14 @@ impl IntoLower for ast::OutputBlock {
let address = self.find("to").into_lower(ctx)?.unwrap_or_default();
let datum = self.find("datum").into_lower(ctx)?.unwrap_or_default();
let amount = self.find("amount").into_lower(ctx)?.unwrap_or_default();
let declared_ix = self.declared_index;

Ok(ir::Output {
address,
datum,
amount,
optional: self.optional,
declared_index: ir::Expression::Number(declared_ix as i128),
})
}
}
Expand Down
25 changes: 23 additions & 2 deletions crates/tx3-lang/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,32 @@ impl AstNode for TxDef {
let mut signers = None;
let mut metadata = None;

let mut declared_index: usize = 0;

for item in inner {
match item.as_rule() {
Rule::locals_block => locals = Some(LocalsBlock::parse(item)?),
Rule::reference_block => references.push(ReferenceBlock::parse(item)?),
Rule::input_block => inputs.push(InputBlock::parse(item)?),
Rule::output_block => outputs.push(OutputBlock::parse(item)?),
Rule::output_block => {
let mut ob = OutputBlock::parse(item)?;
ob.declared_index = declared_index;
declared_index += 1;
outputs.push(ob);
}
Rule::validity_block => validity = Some(ValidityBlock::parse(item)?),
Rule::mint_block => mints.push(MintBlock::parse(item)?),
Rule::burn_block => burns.push(MintBlock::parse(item)?),
Rule::chain_specific_block => adhoc.push(ChainSpecificBlock::parse(item)?),
Rule::chain_specific_block => {
let mut csb = ChainSpecificBlock::parse(item)?;
let ChainSpecificBlock::Cardano(cardano_block) = &mut csb;
if let crate::cardano::CardanoBlock::Publish(pb) = cardano_block {
pb.declared_index = declared_index;
declared_index += 1;
}

adhoc.push(csb);
}
Rule::collateral_block => collateral.push(CollateralBlock::parse(item)?),
Rule::signers_block => signers = Some(SignersBlock::parse(item)?),
Rule::metadata_block => metadata = Some(MetadataBlock::parse(item)?),
Expand Down Expand Up @@ -617,6 +633,8 @@ impl AstNode for OutputBlock {
optional,
fields,
span,
// Default to 0 and set it later
declared_index: 0,
})
}

Expand Down Expand Up @@ -2464,6 +2482,7 @@ mod tests {
}))),
],
span: Span::DUMMY,
declared_index: 0,
}
);

Expand Down Expand Up @@ -2817,4 +2836,6 @@ mod tests {
test_parsing!(list_concat);

test_parsing!(buidler_fest_2026);

test_parsing!(cardano_publish_min_utxo);
}
3 changes: 3 additions & 0 deletions crates/tx3-tir/src/model/v1beta0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ pub struct Output {
pub datum: Expression,
pub amount: Expression,
pub optional: bool,
#[serde(default)]
pub declared_index: Expression,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -522,6 +524,7 @@ impl Node for Output {
datum: self.datum.apply(visitor)?,
amount: self.amount.apply(visitor)?,
optional: self.optional,
declared_index: self.declared_index,
};

Ok(visited)
Expand Down
1 change: 1 addition & 0 deletions crates/tx3-tir/src/reduce/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,7 @@ impl Composite for Output {
datum: f(self.datum)?,
amount: f(self.amount)?,
optional: self.optional,
declared_index: self.declared_index,
})
}
}
Expand Down
6 changes: 4 additions & 2 deletions examples/asteria.ast
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@
"dummy": false,
"start": 1158,
"end": 1379
}
},
"declared_index": 0
},
{
"name": null,
Expand Down Expand Up @@ -651,7 +652,8 @@
"dummy": false,
"start": 1385,
"end": 1449
}
},
"declared_index": 1
}
],
"validity": null,
Expand Down
10 changes: 8 additions & 2 deletions examples/asteria.move_ship.tir
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
},
{
"address": {
Expand Down Expand Up @@ -1262,7 +1265,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 1
}
}
],
"validity": null,
Expand Down
9 changes: 6 additions & 3 deletions examples/buidler_fest_2026.ast
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,8 @@
"dummy": false,
"start": 958,
"end": 1063
}
},
"declared_index": 0
},
{
"name": {
Expand Down Expand Up @@ -672,7 +673,8 @@
"dummy": false,
"start": 1069,
"end": 1246
}
},
"declared_index": 1
},
{
"name": {
Expand Down Expand Up @@ -733,7 +735,8 @@
"dummy": false,
"start": 1252,
"end": 1331
}
},
"declared_index": 2
}
],
"validity": {
Expand Down
15 changes: 12 additions & 3 deletions examples/buidler_fest_2026.buy_ticket.tir
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,10 @@
]
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 0
}
},
{
"address": {
Expand Down Expand Up @@ -458,7 +461,10 @@
}
}
},
"optional": false
"optional": false,
"declared_index": {
"Number": 1
}
},
{
"address": {
Expand Down Expand Up @@ -486,7 +492,10 @@
}
]
},
"optional": false
"optional": false,
"declared_index": {
"Number": 2
}
}
],
"validity": {
Expand Down
Loading