partner_chains_cardano_offchain/
scripts_data.rs

1use crate::plutus_script;
2use crate::{csl::NetworkTypeExt, plutus_script::PlutusScript};
3use cardano_serialization_lib::NetworkIdKind;
4use ogmios_client::query_network::QueryNetwork;
5use raw_scripts::ScriptId;
6use raw_scripts::{
7	COMMITTEE_CANDIDATE_VALIDATOR, D_PARAMETER_POLICY, D_PARAMETER_VALIDATOR, GOVERNED_MAP_POLICY,
8	GOVERNED_MAP_VALIDATOR, ILLIQUID_CIRCULATION_SUPPLY_AUTHORITY_TOKEN_POLICY,
9	ILLIQUID_CIRCULATION_SUPPLY_VALIDATOR, PERMISSIONED_CANDIDATES_POLICY,
10	PERMISSIONED_CANDIDATES_VALIDATOR, RESERVE_AUTH_POLICY, RESERVE_VALIDATOR,
11	VERSION_ORACLE_POLICY, VERSION_ORACLE_VALIDATOR,
12};
13use serde::Serialize;
14use sidechain_domain::{PolicyId, UtxoId};
15use uplc::PlutusData;
16
17/// Provides convenient access to the addresses and hashes of the partner chain smart contracts.
18/// Data in this struct is derived from the smart contracts, applied parameters and the network.
19#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
20#[serde(rename_all = "camelCase")]
21pub struct ScriptsData {
22	/// Validator scripts addresses.
23	pub addresses: Addresses,
24	/// Policy ids.
25	pub policy_ids: PolicyIds,
26}
27
28/// Bech32 addresses of applied validators in partner-chains smart contracts.
29#[derive(Clone, Debug, Default, Serialize, PartialEq, Eq)]
30#[serde(rename_all = "PascalCase")]
31pub struct Addresses {
32	/// Address of committee candidate validator script
33	pub committee_candidate_validator: String,
34	/// Address of D-parameter validator script
35	pub d_parameter_validator: String,
36	/// Address of illiquid circulation supply validator script
37	pub illiquid_circulation_supply_validator: String,
38	/// Address of permissioned candidates validator script
39	pub permissioned_candidates_validator: String,
40	/// Address of reserve validator script
41	pub reserve_validator: String,
42	/// Address of version oracle validator script
43	pub version_oracle_validator: String,
44	/// Address of governed map validator script
45	pub governed_map_validator: String,
46}
47
48/// Policy IDs of applied scripts in partner-chains smart contracts.
49#[derive(Clone, Debug, Default, Serialize, PartialEq, Eq)]
50#[serde(rename_all = "PascalCase")]
51pub struct PolicyIds {
52	/// PolicyId of D-parameter minting policy
53	pub d_parameter: PolicyId,
54	/// PolicyId of permissioned candidates minting policy
55	pub permissioned_candidates: PolicyId,
56	/// PolicyId of reserve auth minting policy
57	pub reserve_auth: PolicyId,
58	/// PolicyId of version oracle minting policy
59	pub version_oracle: PolicyId,
60	/// PolicyId of governed map minting policy
61	pub governed_map: PolicyId,
62	/// PolicyId of illiquid circulation supply auth token policy
63	pub illiquid_circulation_supply_auth_token: PolicyId,
64}
65
66/// Returns [ScriptsData] of the smart contracts for the partner chain identified by `genesis_utxo`.
67pub fn get_scripts_data(
68	genesis_utxo: UtxoId,
69	network: NetworkIdKind,
70) -> anyhow::Result<ScriptsData> {
71	let version_oracle_data = version_oracle(genesis_utxo, network)?;
72	let committee_candidate_validator =
73		plutus_script![COMMITTEE_CANDIDATE_VALIDATOR, genesis_utxo]?;
74	let d_parameter_data = d_parameter_scripts(genesis_utxo, network)?;
75	let illiquid_circulation_supply_validator = plutus_script![
76		ILLIQUID_CIRCULATION_SUPPLY_VALIDATOR,
77		version_oracle_data.policy_id_as_plutus_data()
78	]?;
79	let permissioned_candidates_data = permissioned_candidates_scripts(genesis_utxo, network)?;
80	let reserve = reserve_scripts(genesis_utxo, network)?;
81	let governed_map_data = governed_map_scripts(genesis_utxo, network)?;
82	Ok(ScriptsData {
83		addresses: Addresses {
84			committee_candidate_validator: committee_candidate_validator.address_bech32(network)?,
85			d_parameter_validator: d_parameter_data.validator_address.clone(),
86			illiquid_circulation_supply_validator: illiquid_circulation_supply_validator
87				.address_bech32(network)?,
88			permissioned_candidates_validator: permissioned_candidates_data
89				.validator_address
90				.clone(),
91			reserve_validator: reserve.validator.address_bech32(network)?,
92			version_oracle_validator: version_oracle_data.validator_address.clone(),
93			governed_map_validator: governed_map_data.validator_address.clone(),
94		},
95		policy_ids: PolicyIds {
96			d_parameter: d_parameter_data.policy_id(),
97			permissioned_candidates: permissioned_candidates_data.policy_id(),
98			reserve_auth: reserve.auth_policy.policy_id(),
99			version_oracle: version_oracle_data.policy_id(),
100			governed_map: governed_map_data.policy_id(),
101			illiquid_circulation_supply_auth_token: reserve
102				.illiquid_circulation_supply_auth_token_policy
103				.policy_id(),
104		},
105	})
106}
107
108/// Returns [ScriptsData] of the smart contracts for the partner chain identified by `genesis_utxo`,
109/// for the network configured in `client`.
110pub async fn get_scripts_data_with_ogmios(
111	genesis_utxo: UtxoId,
112	client: &impl QueryNetwork,
113) -> anyhow::Result<ScriptsData> {
114	let network = client.shelley_genesis_configuration().await?.network.to_csl();
115	get_scripts_data(genesis_utxo, network)
116}
117
118/// Type representing a PlutusScript validator and policy pair.
119pub struct PlutusScriptData {
120	/// Cardano validator script.
121	pub validator: PlutusScript,
122	/// Bech32 address of `validator`.
123	pub validator_address: String,
124	/// Cardano minding policy.
125	pub policy: PlutusScript,
126}
127
128impl PlutusScriptData {
129	/// Returns [PolicyId] of [PlutusScriptData].
130	pub fn policy_id(&self) -> PolicyId {
131		self.policy.policy_id()
132	}
133
134	/// Returns [PolicyId] of [PlutusScriptData] as [PlutusData].
135	pub fn policy_id_as_plutus_data(&self) -> PlutusData {
136		PlutusData::BoundedBytes(self.policy.script_hash().to_vec().into())
137	}
138}
139
140/// Returns version oracle data required by other scripts.
141pub fn version_oracle(
142	genesis_utxo: UtxoId,
143	network: NetworkIdKind,
144) -> Result<PlutusScriptData, anyhow::Error> {
145	let validator = plutus_script![VERSION_ORACLE_VALIDATOR, genesis_utxo]?;
146	let validator_address = validator.address_bech32(network)?;
147	let policy =
148		plutus_script![VERSION_ORACLE_POLICY, genesis_utxo, validator.address_data(network)?]?;
149	Ok(PlutusScriptData { validator, validator_address, policy })
150}
151
152pub(crate) fn governed_map_scripts(
153	genesis_utxo: UtxoId,
154	network: NetworkIdKind,
155) -> Result<PlutusScriptData, anyhow::Error> {
156	let version_oracle_data = version_oracle(genesis_utxo, network)?;
157	let validator = plutus_script![
158		GOVERNED_MAP_VALIDATOR,
159		ScriptId::GovernedMapValidator,
160		genesis_utxo,
161		version_oracle_data.policy_id()
162	]?;
163	let validator_address = validator.address_bech32(network)?;
164	let policy = plutus_script![
165		GOVERNED_MAP_POLICY,
166		ScriptId::GovernedMapPolicy,
167		genesis_utxo,
168		version_oracle_data.policy_id()
169	]?;
170	Ok(PlutusScriptData { validator, validator_address, policy })
171}
172
173pub(crate) fn d_parameter_scripts(
174	genesis_utxo: UtxoId,
175	network: NetworkIdKind,
176) -> Result<PlutusScriptData, anyhow::Error> {
177	let version_oracle_data = version_oracle(genesis_utxo, network)?;
178	let validator =
179		plutus_script![D_PARAMETER_VALIDATOR, genesis_utxo, version_oracle_data.policy_id()]?;
180	let validator_address = validator.address_bech32(network)?;
181	let policy = plutus_script![
182		D_PARAMETER_POLICY,
183		genesis_utxo,
184		version_oracle_data.policy_id(),
185		validator.address_data(network)?
186	]?;
187	Ok(PlutusScriptData { validator, validator_address, policy })
188}
189
190pub(crate) fn permissioned_candidates_scripts(
191	genesis_utxo: UtxoId,
192	network: NetworkIdKind,
193) -> Result<PlutusScriptData, anyhow::Error> {
194	let version_oracle_data = version_oracle(genesis_utxo, network)?;
195	let validator = plutus_script![
196		PERMISSIONED_CANDIDATES_VALIDATOR,
197		genesis_utxo,
198		version_oracle_data.policy_id()
199	]?;
200	let validator_address = validator.address_bech32(network)?;
201	let policy = plutus_script![
202		PERMISSIONED_CANDIDATES_POLICY,
203		genesis_utxo,
204		version_oracle_data.policy_id(),
205		validator.address_data(network)?
206	]?;
207	Ok(PlutusScriptData { validator, validator_address, policy })
208}
209
210pub(crate) fn registered_candidates_scripts(
211	genesis_utxo: UtxoId,
212) -> Result<PlutusScript, anyhow::Error> {
213	let validator = plutus_script![COMMITTEE_CANDIDATE_VALIDATOR, genesis_utxo]?;
214	Ok(validator)
215}
216
217#[derive(Clone, Debug)]
218pub(crate) struct ReserveScripts {
219	pub(crate) validator: PlutusScript,
220	pub(crate) auth_policy: PlutusScript,
221	pub(crate) illiquid_circulation_supply_validator: PlutusScript,
222	pub(crate) illiquid_circulation_supply_auth_token_policy: PlutusScript,
223}
224
225pub(crate) fn reserve_scripts(
226	genesis_utxo: UtxoId,
227	network: NetworkIdKind,
228) -> Result<ReserveScripts, anyhow::Error> {
229	let version_oracle_data = version_oracle(genesis_utxo, network)?;
230	let validator =
231		plutus_script![RESERVE_VALIDATOR, version_oracle_data.policy_id_as_plutus_data()]?;
232	let auth_policy =
233		plutus_script![RESERVE_AUTH_POLICY, version_oracle_data.policy_id_as_plutus_data()]?;
234	let illiquid_circulation_supply_validator = plutus_script![
235		ILLIQUID_CIRCULATION_SUPPLY_VALIDATOR,
236		version_oracle_data.policy_id_as_plutus_data()
237	]?;
238	let illiquid_circulation_supply_auth_token_policy = plutus_script![
239		ILLIQUID_CIRCULATION_SUPPLY_AUTHORITY_TOKEN_POLICY,
240		ScriptId::IlliquidCirculationSupplyAuthorityTokenPolicy,
241		version_oracle_data.policy_id_as_plutus_data()
242	]?;
243	Ok(ReserveScripts {
244		validator,
245		auth_policy,
246		illiquid_circulation_supply_validator,
247		illiquid_circulation_supply_auth_token_policy,
248	})
249}
250
251#[cfg(test)]
252mod tests {
253	use crate::scripts_data::{Addresses, PolicyIds, ScriptsData};
254	use cardano_serialization_lib::NetworkIdKind;
255	use hex_literal::hex;
256	use pretty_assertions::assert_eq;
257	use sidechain_domain::{McTxHash, PolicyId, UtxoId};
258
259	pub(crate) const TEST_PARAMS: UtxoId = UtxoId {
260		tx_hash: McTxHash(hex!("8ea10040249ad3033ae7c4d4b69e0b2e2b50a90741b783491cb5ddf8ced0d861")),
261		index: sidechain_domain::UtxoIndex(0),
262	};
263
264	pub(crate) fn scripts_data_test_vector() -> ScriptsData {
265		ScriptsData {
266			addresses: Addresses {
267				committee_candidate_validator:
268					"addr_test1wzx9p24eryn2h8xnns583edq82y5qkwey7wgqygzr34y6dqny7nsj".into(),
269				d_parameter_validator:
270					"addr_test1wqq69vap60sf6nw7q75xcqd6ecch95vx6qylju26qgp429szlhwea".into(),
271				permissioned_candidates_validator:
272					"addr_test1wqhp3xkm7ntcy0q9cjnttngx94vyn4a7fgyyk5cegw3rkhc4pjahq".into(),
273				illiquid_circulation_supply_validator:
274					"addr_test1wqzuuqa0q0le6t8j0gu4pz8mq3khmzfth0qgfc0r6cur7hcqy0py6".into(),
275				reserve_validator:
276					"addr_test1wzfnr6alsdhyykph86k946yyrr5ry7exxt07fr40qdagvysj306ph".into(),
277				version_oracle_validator:
278					"addr_test1wpadfxldpsgn3zk5yswm7ygwgmfmawxaj90dl40s77jajfgnker5v".into(),
279				governed_map_validator:
280					"addr_test1wr6unjvhtdvej4txavu5h4mt0xa0uylm39jm9fvg0tmt4pc5h4akm".into(),
281			},
282			policy_ids: PolicyIds {
283				d_parameter: PolicyId(hex!(
284					"95543debb3d64e2c35fd48129d7a3584870ea9db47859c39ee906c1b"
285				)),
286				permissioned_candidates: PolicyId(hex!(
287					"d29bc1e7643976641cd76888009207f20f0e92c1fca7f43deb8f0f0c"
288				)),
289				reserve_auth: PolicyId(hex!(
290					"7b9a65e15549703c81ebaf402f209a55f3b40e655939ad0205aa3cff"
291				)),
292				version_oracle: PolicyId(hex!(
293					"d3d6eadae137f555653094f67fe29f7beab90d55d04ca05c1ab9d2af"
294				)),
295				governed_map: PolicyId(hex!(
296					"1b7c0fa2b32502b8e92ec529f1fe3931febf0b7829f23dc514d88aa0"
297				)),
298				illiquid_circulation_supply_auth_token: PolicyId(hex!(
299					"6bc5e936c143b2758caea2fbf6d4e921400b54f9f74bea55ed1b08e2"
300				)),
301			},
302		}
303	}
304
305	// Expected values are the ones obtained from pc-contracts-cli for the TEST_PARAMS.
306	#[test]
307	fn test_get_scripts_data() {
308		let actual =
309			crate::scripts_data::get_scripts_data(TEST_PARAMS, NetworkIdKind::Testnet).unwrap();
310		assert_eq!(scripts_data_test_vector(), actual);
311	}
312}