partner_chains_cardano_offchain/bridge/
create_utxos.rs

1use crate::{
2	await_tx::AwaitTx,
3	bridge::ICSData,
4	cardano_keys::CardanoPaymentSigningKey,
5	csl::{
6		Costs, MultiAssetExt, OgmiosUtxoExt, Script, TransactionBuilderExt, TransactionContext,
7		TransactionExt, TransactionOutputAmountBuilderExt, get_builder_config, unit_plutus_data,
8	},
9	governance::GovernanceData,
10	multisig::{MultiSigSmartContractResult, submit_or_create_tx_to_sign},
11	scripts_data::ICSScripts,
12};
13use cardano_serialization_lib::{
14	Int, JsError, MultiAsset, Transaction, TransactionBuilder, TransactionOutput,
15	TransactionOutputBuilder,
16};
17use ogmios_client::{
18	query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId},
19	query_network::QueryNetwork,
20	transactions::Transactions,
21};
22use sidechain_domain::UtxoId;
23use std::num::NonZero;
24
25/// Creates "blessed" UTXOs at the ICS (Bridge) validator.
26pub async fn create_validator_utxos<
27	T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId,
28	A: AwaitTx,
29>(
30	genesis_utxo: UtxoId,
31	amount: NonZero<u64>,
32	payment_key: &CardanoPaymentSigningKey,
33	client: &T,
34	await_tx: &A,
35) -> anyhow::Result<MultiSigSmartContractResult> {
36	let payment_ctx = TransactionContext::for_payment_key(payment_key, client).await?;
37	let governance = GovernanceData::get(genesis_utxo, client).await?;
38	let ics_data = ICSData::get(genesis_utxo, &payment_ctx, client).await?;
39
40	submit_or_create_tx_to_sign(
41		&governance,
42		payment_ctx,
43		|costs, ctx| create_utxos_tx(amount.get(), &ics_data, &governance, costs, &ctx),
44		"Create Bridge UTXOs",
45		client,
46		await_tx,
47	)
48	.await
49}
50
51fn create_utxos_tx(
52	amount: u64,
53	ics_data: &ICSData,
54	governance: &GovernanceData,
55	costs: Costs,
56	ctx: &TransactionContext,
57) -> anyhow::Result<Transaction> {
58	let mut tx_builder = TransactionBuilder::new(&get_builder_config(ctx)?);
59
60	let gov_tx_input = governance.utxo_id_as_tx_input();
61	tx_builder.add_mint_one_script_token_using_reference_script(
62		&governance.policy.script(),
63		&gov_tx_input,
64		&costs,
65	)?;
66
67	tx_builder.add_mint_script_token_using_reference_script(
68		&Script::Plutus(ics_data.scripts.auth_policy.clone()),
69		&ics_data.auth_policy_version_utxo.to_csl_tx_input(),
70		&Int::new(&amount.into()),
71		&costs,
72	)?;
73	// Create ICS Authorized Outputs. These contain special ICS Authority Token,
74	// that prevents UTxOs from being merged all into one.
75	for _ in 0u64..amount {
76		tx_builder.add_output(&ics_validator_output(&ics_data.scripts, ctx)?)?;
77	}
78
79	let tx = tx_builder.balance_update_and_build(ctx)?.remove_native_script_witnesses();
80
81	Ok(tx)
82}
83
84fn ics_validator_output(
85	scripts: &ICSScripts,
86	ctx: &TransactionContext,
87) -> Result<TransactionOutput, JsError> {
88	let amount_builder = TransactionOutputBuilder::new()
89		.with_address(&scripts.validator.address(ctx.network))
90		.with_plutus_data(&unit_plutus_data())
91		.next()?;
92	let ma = MultiAsset::new().with_asset_amount(&scripts.auth_policy.empty_name_asset(), 1u64)?;
93
94	amount_builder.with_minimum_ada_and_asset(&ma, ctx)?.build()
95}