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