From 07956950d5393fe8ab4464c081cff43717831753 Mon Sep 17 00:00:00 2001 From: Krisztian Pinter Date: Thu, 16 Jan 2025 11:49:29 +0100 Subject: [PATCH 1/7] reserve settings update tx submission --- toolkit/offchain/src/csl.rs | 5 +- toolkit/offchain/src/reserve/mod.rs | 35 ++- .../offchain/src/reserve/update_settings.rs | 245 +++++++----------- toolkit/offchain/src/scripts_data.rs | 8 +- toolkit/offchain/tests/integration_tests.rs | 57 +++- 5 files changed, 191 insertions(+), 159 deletions(-) diff --git a/toolkit/offchain/src/csl.rs b/toolkit/offchain/src/csl.rs index 9ca2f8fa1..090949838 100644 --- a/toolkit/offchain/src/csl.rs +++ b/toolkit/offchain/src/csl.rs @@ -88,6 +88,7 @@ pub(crate) fn get_builder_config( .ref_script_coins_per_byte(&convert_reference_script_costs( &protocol_parameters.min_fee_reference_scripts.clone(), )?) + .deduplicate_explicit_ref_inputs_with_regular_inputs(true) .build() } @@ -289,7 +290,7 @@ impl MainchainPrivateKeyExt for MainchainPrivateKey { } } -pub(crate) struct TransactionContext { +pub struct TransactionContext { /// This key is added as required signer and used to sign the transaction. pub(crate) payment_key: PrivateKey, /// Used to pay for the transaction fees and uncovered transaction inputs @@ -302,7 +303,7 @@ pub(crate) struct TransactionContext { impl TransactionContext { /// Gets `TransactionContext`, having UTXOs for the given payment key and the network configuration, /// required to perform most of the partner-chains smart contract operations. - pub(crate) async fn for_payment_key( + pub async fn for_payment_key( payment_signing_key: [u8; 32], client: &C, ) -> Result { diff --git a/toolkit/offchain/src/reserve/mod.rs b/toolkit/offchain/src/reserve/mod.rs index 9ec776825..9467415e4 100644 --- a/toolkit/offchain/src/reserve/mod.rs +++ b/toolkit/offchain/src/reserve/mod.rs @@ -2,6 +2,7 @@ use crate::{csl::TransactionContext, scripts_data}; use anyhow::anyhow; +use cardano_serialization_lib::PlutusData; use init::find_script_utxo; use ogmios_client::{ query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId}, @@ -9,6 +10,7 @@ use ogmios_client::{ transactions::Transactions, types::OgmiosUtxo, }; +use partner_chains_plutus_data::reserve::ReserveDatum; use sidechain_domain::UtxoId; pub mod create; @@ -17,14 +19,35 @@ pub mod init; pub mod update_settings; #[derive(Clone, Debug)] -pub(crate) struct ReserveData { - pub(crate) scripts: scripts_data::ReserveScripts, - pub(crate) auth_policy_version_utxo: OgmiosUtxo, - pub(crate) validator_version_utxo: OgmiosUtxo, - pub(crate) illiquid_circulation_supply_validator_version_utxo: OgmiosUtxo, +pub struct ReserveData { + pub scripts: scripts_data::ReserveScripts, + pub auth_policy_version_utxo: OgmiosUtxo, + pub validator_version_utxo: OgmiosUtxo, + pub illiquid_circulation_supply_validator_version_utxo: OgmiosUtxo, } -pub(crate) async fn get_reserve_data< +impl ReserveData { + pub async fn get_reserve_settings< + T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, + >( + &self, + ctx: &TransactionContext, + client: &T, + ) -> Result, anyhow::Error> { + let validator_address = self.scripts.validator.address(ctx.network).to_bech32(None)?; + let validator_utxos = client.query_utxos(&[validator_address]).await?; + + Ok(validator_utxos.into_iter().find_map(|utxo| { + utxo.clone() + .datum + .and_then(|d| PlutusData::from_bytes(d.bytes).ok()) + .and_then(|d| ReserveDatum::try_from(d).ok()) + .map(|d| (utxo, d)) + })) + } +} + +pub async fn get_reserve_data< T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, >( genesis_utxo: UtxoId, diff --git a/toolkit/offchain/src/reserve/update_settings.rs b/toolkit/offchain/src/reserve/update_settings.rs index d7eaba5e8..cf9c4461c 100644 --- a/toolkit/offchain/src/reserve/update_settings.rs +++ b/toolkit/offchain/src/reserve/update_settings.rs @@ -16,17 +16,99 @@ //! * Reserve Validator Version Utxo //! * Governance Policy Script +use super::get_reserve_data; use super::ReserveData; -use crate::{csl::*, init_governance::GovernanceData}; +use crate::{ + await_tx::AwaitTx, csl::*, init_governance::get_governance_data, + init_governance::GovernanceData, +}; use cardano_serialization_lib::*; +use ogmios_client::types::OgmiosUtxo; +use ogmios_client::{ + query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId}, + query_network::QueryNetwork, + transactions::Transactions, +}; use partner_chains_plutus_data::reserve::{ReserveDatum, ReserveRedeemer}; +use sidechain_domain::{McTxHash, ScriptHash, UtxoId}; + +pub async fn update_reserve_settings< + T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, + A: AwaitTx, +>( + genesis_utxo: UtxoId, + payment_key: [u8; 32], + total_accrued_function_script_hash: ScriptHash, + reserve_initial_incentive_amount: u64, + client: &T, + await_tx: &A, +) -> anyhow::Result { + let ctx = TransactionContext::for_payment_key(payment_key, client).await?; + let governance = get_governance_data(genesis_utxo, client).await?; + let reserve = get_reserve_data(genesis_utxo, &ctx, client).await?; + let (reserve_utxo, mut reserve_settings) = reserve + .get_reserve_settings(&ctx, client) + .await? + .expect("reserve utxo must exist"); + + reserve_settings.mutable_settings.total_accrued_function_script_hash = + total_accrued_function_script_hash; + reserve_settings.mutable_settings.initial_incentive = reserve_initial_incentive_amount; + + let tx_to_evaluate = update_reserve_settings_tx( + &reserve_settings, + &reserve, + &governance, + &zero_ex_units(), + &reserve_utxo, + &zero_ex_units(), + &ctx, + )?; + + let evaluate_response = client.evaluate_transaction(&tx_to_evaluate.to_bytes()).await?; + + let budgets = get_validator_budgets(evaluate_response); + let gov_cost = budgets + .mint_ex_units + .first() + .expect("Every Update Reserve Settings transaction should have one mint") + .clone(); + let reserve_cost = budgets + .spend_ex_units + .first() + .expect("Every Update Reserve Settings transaction should have one spend") + .clone(); + + let tx = update_reserve_settings_tx( + &reserve_settings, + &reserve, + &governance, + &gov_cost, + &reserve_utxo, + &reserve_cost, + &ctx, + )?; + let signed_tx = ctx.sign(&tx).to_bytes(); + let res = client.submit_transaction(&signed_tx).await.map_err(|e| { + anyhow::anyhow!( + "Update Reserve Settings transaction request failed: {}, tx bytes: {}", + e, + hex::encode(signed_tx) + ) + })?; + let tx_id = res.transaction.id; + log::info!("Update Reserve Settings transaction submitted: {}", hex::encode(tx_id)); + await_tx.await_tx_output(client, UtxoId::new(tx_id, 0)).await?; + Ok(McTxHash(tx_id)) +} fn update_reserve_settings_tx( datum: &ReserveDatum, reserve: &ReserveData, governance: &GovernanceData, - governance_script_cost: ExUnits, - redeemer_script_cost: ExUnits, + governance_script_cost: &ExUnits, + reserve_utxo: &OgmiosUtxo, + reserve_script_cost: &ExUnits, ctx: &TransactionContext, ) -> Result { let mut tx_builder = TransactionBuilder::new(&get_builder_config(ctx)?); @@ -35,9 +117,6 @@ fn update_reserve_settings_tx( { let mut inputs = TxInputsBuilder::new(); - let utxo = &reserve.validator_version_utxo; - let input = utxo.to_csl_tx_input(); - let amount = &utxo.value.to_csl()?; let witness = PlutusWitness::new_with_ref_without_datum( &PlutusScriptSource::new_ref_input( &reserve.scripts.validator.csl_script_hash(), @@ -50,10 +129,11 @@ fn update_reserve_settings_tx( // CSL will set redeemer index for the index of script input after sorting transaction inputs &0u32.into(), &ReserveRedeemer::UpdateReserve { governance_version: 1u64 }.into(), - &redeemer_script_cost, + reserve_script_cost, ), ); - inputs.add_plutus_script_input(&witness, &input, amount); + let amount = reserve_utxo.value.to_csl()?; + inputs.add_plutus_script_input(&witness, &reserve_utxo.to_csl_tx_input(), &amount); tx_builder.set_inputs(&inputs); } @@ -64,7 +144,7 @@ fn update_reserve_settings_tx( .with_plutus_data(&(datum.clone().into())) .with_script_ref(&ScriptRef::new_plutus_script(&reserve.scripts.validator.to_csl())) .next()?; - let mut val = reserve.validator_version_utxo.value.to_csl()?; + let mut val = reserve_utxo.value.to_csl()?; let output = amount_builder.with_value(&val).build()?; let min_ada = MinOutputAdaCalculator::new( &output, @@ -82,148 +162,23 @@ fn update_reserve_settings_tx( tx_builder.add_mint_one_script_token_using_reference_script( &governance.policy_script, &gov_tx_input, - &governance_script_cost, + governance_script_cost, )?; tx_builder.add_script_reference_input( &reserve.illiquid_circulation_supply_validator_version_utxo.to_csl_tx_input(), reserve.scripts.illiquid_circulation_supply_validator.bytes.len(), ); - tx_builder.add_required_signer(&ctx.payment_key_hash()); - - tx_builder.balance_update_and_build(ctx) -} - -#[cfg(test)] -mod tests { - - use cardano_serialization_lib::{ExUnits, Language, NetworkIdKind}; - use hex_literal::hex; - use ogmios_client::types::{OgmiosTx, OgmiosUtxo}; - use partner_chains_plutus_data::reserve::ReserveDatum; - use sidechain_domain::{AssetId, AssetName, PolicyId}; - - use super::update_reserve_settings_tx; - use crate::{ - csl::TransactionContext, - init_governance::GovernanceData, - plutus_script::PlutusScript, - reserve::ReserveData, - scripts_data::ReserveScripts, - test_values::{make_utxo, payment_addr, payment_key, protocol_parameters}, - }; - - const REWARDS_TOKEN_POLICY_ID: PolicyId = - PolicyId(hex!("1fab25f376bc49a181d03a869ee8eaa3157a3a3d242a619ca7995b2b")); - - // Reward token - const REWARDS_TOKEN_ASSET_NAME_STR: &str = "52657761726420746f6b656e"; - - #[test] - fn update_reserve_settings_tx_test() { - let parameters = crate::reserve::create::ReserveParameters { - initial_incentive: 100, - total_accrued_function_script_hash: PolicyId([233u8; 28]), - token: AssetId { - policy_id: REWARDS_TOKEN_POLICY_ID, - asset_name: AssetName::from_hex_unsafe(REWARDS_TOKEN_ASSET_NAME_STR), - }, - initial_deposit: 500000, - }; - - let reserve: ReserveData = ReserveData { - scripts: ReserveScripts { - validator: test_validator_script(), - auth_policy: test_auth_policy_script(), - illiquid_circulation_supply_validator: test_ics_validator_script(), - }, - auth_policy_version_utxo: test_auth_policy_version_utxo(), - validator_version_utxo: test_validator_version_utxo(), - illiquid_circulation_supply_validator_version_utxo: test_ics_validator_version_utxo(), - }; - let tx = update_reserve_settings_tx( - &(¶meters).into(), - &reserve, - &test_governance_data(), - governance_script_cost(), - redeemer_script_cost(), - &test_transaction_context(), - ) - .unwrap(); - - let body = tx.body(); - let inputs = body.inputs(); - let outputs = body.outputs(); - - // Both inputs are used to cover transaction - assert_eq!( - inputs.get(0).to_string(), - "1212121212121212121212121212121212121212121212121212121212121212#0" - ); - assert_eq!( - inputs.get(1).to_string(), - "7474747474747474747474747474747474747474747474747474747474747474#3" - ); - assert_eq!( - outputs.get(0).address(), - test_validator_script().address(cardano_serialization_lib::NetworkIdKind::Testnet) - ); - assert_eq!( - outputs.get(1).address().to_hex(), - "6032230eeaaae0ff7a97e7f088e65874bd79c0fe2a99399f795e84543a" - ); - assert_eq!(outputs.get(0).plutus_data().unwrap(), ReserveDatum::from(¶meters).into()); - } - - fn test_transaction_context() -> TransactionContext { - TransactionContext { - payment_key: payment_key(), - payment_key_utxos: vec![make_utxo(116u8, 3, 996272387, &payment_addr())], - network: NetworkIdKind::Testnet, - protocol_parameters: protocol_parameters(), - } - } - fn test_validator_script() -> PlutusScript { - PlutusScript { bytes: hex!("445566").to_vec(), language: Language::new_plutus_v2() } - } - - fn test_auth_policy_script() -> PlutusScript { - PlutusScript { bytes: hex!("556677").to_vec(), language: Language::new_plutus_v2() } - } - - fn test_ics_validator_script() -> PlutusScript { - PlutusScript { bytes: hex!("667788").to_vec(), language: Language::new_plutus_v2() } - } - - fn test_governance_script() -> PlutusScript { - PlutusScript { bytes: hex!("112233").to_vec(), language: Language::new_plutus_v2() } - } - - fn test_governance_input() -> OgmiosUtxo { - OgmiosUtxo { transaction: OgmiosTx { id: [16; 32] }, index: 0, ..Default::default() } - } - - fn test_auth_policy_version_utxo() -> OgmiosUtxo { - OgmiosUtxo { transaction: OgmiosTx { id: [17; 32] }, index: 0, ..Default::default() } - } - - fn test_validator_version_utxo() -> OgmiosUtxo { - OgmiosUtxo { transaction: OgmiosTx { id: [18; 32] }, index: 0, ..Default::default() } - } - - fn test_ics_validator_version_utxo() -> OgmiosUtxo { - OgmiosUtxo { transaction: OgmiosTx { id: [19; 32] }, index: 0, ..Default::default() } - } - - fn test_governance_data() -> GovernanceData { - GovernanceData { policy_script: test_governance_script(), utxo: test_governance_input() } - } + tx_builder.add_script_reference_input( + &reserve.auth_policy_version_utxo.to_csl_tx_input(), + reserve.scripts.auth_policy.bytes.len(), + ); + tx_builder.add_script_reference_input( + &reserve.validator_version_utxo.to_csl_tx_input(), + reserve.scripts.validator.bytes.len(), + ); - fn governance_script_cost() -> ExUnits { - ExUnits::new(&100u64.into(), &200u64.into()) - } + tx_builder.add_required_signer(&ctx.payment_key_hash()); - fn redeemer_script_cost() -> ExUnits { - ExUnits::new(&300u64.into(), &400u64.into()) - } + tx_builder.balance_update_and_build(ctx) } diff --git a/toolkit/offchain/src/scripts_data.rs b/toolkit/offchain/src/scripts_data.rs index c12caa1cd..8cad15d89 100644 --- a/toolkit/offchain/src/scripts_data.rs +++ b/toolkit/offchain/src/scripts_data.rs @@ -212,10 +212,10 @@ pub(crate) fn registered_candidates_scripts( } #[derive(Clone, Debug)] -pub(crate) struct ReserveScripts { - pub(crate) validator: PlutusScript, - pub(crate) auth_policy: PlutusScript, - pub(crate) illiquid_circulation_supply_validator: PlutusScript, +pub struct ReserveScripts { + pub validator: PlutusScript, + pub auth_policy: PlutusScript, + pub illiquid_circulation_supply_validator: PlutusScript, } pub(crate) fn reserve_scripts( diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index 8810cb11f..e2f26876f 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -16,10 +16,12 @@ use ogmios_client::{ }; use partner_chains_cardano_offchain::{ await_tx::{AwaitTx, FixedDelayRetries}, + csl::TransactionContext, d_param, init_governance, permissioned_candidates, register::Register, reserve, scripts_data, update_governance, }; +use partner_chains_plutus_data::reserve::ReserveMutableSettings; use sidechain_domain::{ AdaBasedStaking, AssetId, AssetName, AuraPublicKey, CandidateRegistration, DParameter, GrandpaPublicKey, MainchainAddressHash, MainchainPrivateKey, MainchainPublicKey, @@ -66,6 +68,13 @@ const REWARDS_TOKEN_ASSET_NAME_STR: &str = "52657761726420746f6b656e"; const INITIAL_DEPOSIT_AMOUNT: u64 = 500000; const DEPOSIT_AMOUNT: u64 = 100000; +const UPDATED_TOTAL_ACCRUED_FUNCTION_SCRIPT_HASH: PolicyId = PolicyId([234u8; 28]); +const UPDATED_INITIAL_INCENTIVE: u64 = 101; +const UPDATED_MUTABLE_SETTINGS: ReserveMutableSettings = ReserveMutableSettings { + total_accrued_function_script_hash: UPDATED_TOTAL_ACCRUED_FUNCTION_SCRIPT_HASH, + initial_incentive: UPDATED_INITIAL_INCENTIVE, +}; + #[tokio::test] async fn governance_flow() { let image = GenericImage::new(TEST_IMAGE, TEST_IMAGE_TAG); @@ -122,6 +131,8 @@ async fn reserve_management_scenario() { assert_reserve_deposited(genesis_utxo, INITIAL_DEPOSIT_AMOUNT, &client).await; run_deposit_to_reserve(genesis_utxo, &client).await; assert_reserve_deposited(genesis_utxo, INITIAL_DEPOSIT_AMOUNT + DEPOSIT_AMOUNT, &client).await; + let _ = run_update_reserve_settings_management(genesis_utxo, &client).await; + assert_mutable_settings_eq(genesis_utxo, UPDATED_MUTABLE_SETTINGS, &client).await; } #[tokio::test] @@ -165,6 +176,7 @@ async fn await_ogmios(ogmios_port: u16) -> Result { /// * "dave" address: addr_test1vphpcf32drhhznv6rqmrmgpuwq06kug0lkg22ux777rtlqst2er0r /// * "eve" address: addr_test1vzzt5pwz3pum9xdgxalxyy52m3aqur0n43pcl727l37ggscl8h7v8 /// * addr_test1vzuasm5nqzh7n909f7wang7apjprpg29l2f9sk6shlt84rqep6nyc - has attached V-function script +/// /// Its hash is 0xf8fbe7316561e57de9ecd1c86ee8f8b512a314ba86499ba9a584bfa8fe2edc8d async fn initial_transaction( client: &T, @@ -317,12 +329,30 @@ async fn run_create_reserve_management< .unwrap() } +async fn run_update_reserve_settings_management< + T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, +>( + genesis_utxo: UtxoId, + client: &T, +) -> McTxHash { + reserve::update_settings::update_reserve_settings( + genesis_utxo, + GOVERNANCE_AUTHORITY_PAYMENT_KEY.0, + UPDATED_TOTAL_ACCRUED_FUNCTION_SCRIPT_HASH, + UPDATED_INITIAL_INCENTIVE, + client, + &FixedDelayRetries::new(Duration::from_millis(500), 100), + ) + .await + .unwrap() +} + async fn run_deposit_to_reserve< T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, >( genesis_utxo: UtxoId, client: &T, -) -> () { +) { reserve::deposit::deposit_to_reserve( reserve::deposit::TokenAmount { token: AssetId { @@ -386,7 +416,7 @@ async fn assert_token_amount_eq( }), "Expected to find UTXO with {} of {}.{} at {}", expected_amount, - hex::encode(&token_policy_id.0), + hex::encode(token_policy_id.0), hex::encode(&token_asset_name.0), address, ); @@ -407,3 +437,26 @@ async fn assert_reserve_deposited( ) .await; } + +async fn assert_mutable_settings_eq( + genesis_utxo: UtxoId, + updated_mutable_settings: ReserveMutableSettings, + client: &T, +) { + let ctx = TransactionContext::for_payment_key(GOVERNANCE_AUTHORITY_PAYMENT_KEY.0, client) + .await + .unwrap(); + let reserve_data = crate::reserve::get_reserve_data(genesis_utxo, &ctx, client).await.unwrap(); + let mutable_settings = reserve_data + .get_reserve_settings(&ctx, client) + .await + .unwrap() + .unwrap() + .1 + .mutable_settings; + assert_eq!( + mutable_settings.total_accrued_function_script_hash, + updated_mutable_settings.total_accrued_function_script_hash + ); + assert_eq!(mutable_settings.initial_incentive, updated_mutable_settings.initial_incentive); +} From af4c8fa28060e60224a314de002119ff7889440b Mon Sep 17 00:00:00 2001 From: Krisztian Pinter Date: Thu, 16 Jan 2025 18:25:13 +0100 Subject: [PATCH 2/7] reserve settings update cmd --- .../smart-contracts-commands/src/reserve.rs | 38 ++++++++++++++++++ .../offchain/src/reserve/update_settings.rs | 40 ++++++++++++++++--- toolkit/offchain/tests/integration_tests.rs | 4 +- toolkit/utils/ogmios-client/src/types.rs | 2 +- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/toolkit/cli/smart-contracts-commands/src/reserve.rs b/toolkit/cli/smart-contracts-commands/src/reserve.rs index a5fb25145..f59ecda2b 100644 --- a/toolkit/cli/smart-contracts-commands/src/reserve.rs +++ b/toolkit/cli/smart-contracts-commands/src/reserve.rs @@ -6,6 +6,7 @@ use partner_chains_cardano_offchain::{ create::{create_reserve_utxo, ReserveParameters}, deposit::{deposit_to_reserve, TokenAmount}, init::init_reserve_management, + update_settings::update_reserve_settings, }, }; use sidechain_domain::{AssetId, ScriptHash, UtxoId}; @@ -17,6 +18,8 @@ pub enum ReserveCmd { Init(InitReserveCmd), Create(CreateReserveCmd), Deposit(DepositReserveCmd), + /// Update reserve management system settings for your chain + UpdateSettings(UpdateReserveSettingsCmd), } impl ReserveCmd { @@ -25,6 +28,7 @@ impl ReserveCmd { Self::Init(cmd) => cmd.execute().await, Self::Create(cmd) => cmd.execute().await, Self::Deposit(cmd) => cmd.execute().await, + Self::UpdateSettings(cmd) => cmd.execute().await, } } } @@ -131,3 +135,37 @@ impl DepositReserveCmd { Ok(()) } } + +#[derive(Clone, Debug, clap::Parser)] +pub struct UpdateReserveSettingsCmd { + #[clap(flatten)] + common_arguments: crate::CommonArguments, + #[clap(flatten)] + payment_key_file: PaymentFilePath, + /// Genesis UTXO of the partner-chain. + #[arg(long, short('c'))] + genesis_utxo: UtxoId, + #[arg(long)] + /// Script hash of the 'total accrued function', also called V-function, that computes how many tokens could be released from the reserve at given moment. + total_accrued_function_script_hash: Option, + #[arg(long)] + /// Incentive amount of tokens. + reserve_initial_incentive_amount: Option, +} + +impl UpdateReserveSettingsCmd { + pub async fn execute(self) -> crate::CmdResult<()> { + let payment_key = self.payment_key_file.read_key()?; + let ogmios_client = client_for_url(&self.common_arguments.ogmios_url).await?; + let _ = update_reserve_settings( + self.genesis_utxo, + payment_key.0, + self.total_accrued_function_script_hash, + self.reserve_initial_incentive_amount, + &ogmios_client, + &FixedDelayRetries::two_minutes(), + ) + .await?; + Ok(()) + } +} diff --git a/toolkit/offchain/src/reserve/update_settings.rs b/toolkit/offchain/src/reserve/update_settings.rs index cf9c4461c..4ac3d25f9 100644 --- a/toolkit/offchain/src/reserve/update_settings.rs +++ b/toolkit/offchain/src/reserve/update_settings.rs @@ -38,8 +38,8 @@ pub async fn update_reserve_settings< >( genesis_utxo: UtxoId, payment_key: [u8; 32], - total_accrued_function_script_hash: ScriptHash, - reserve_initial_incentive_amount: u64, + mut total_accrued_function_script_hash_opt: Option, + mut reserve_initial_incentive_amount_opt: Option, client: &T, await_tx: &A, ) -> anyhow::Result { @@ -51,9 +51,39 @@ pub async fn update_reserve_settings< .await? .expect("reserve utxo must exist"); - reserve_settings.mutable_settings.total_accrued_function_script_hash = - total_accrued_function_script_hash; - reserve_settings.mutable_settings.initial_incentive = reserve_initial_incentive_amount; + if let Some(total_accrued_function_script_hash) = total_accrued_function_script_hash_opt.clone() + { + if total_accrued_function_script_hash + == reserve_settings.mutable_settings.total_accrued_function_script_hash + { + total_accrued_function_script_hash_opt = None; + log::info!( + "Reserve V function hash is already set to {:?}.", + total_accrued_function_script_hash + ); + } else { + reserve_settings.mutable_settings.total_accrued_function_script_hash = + total_accrued_function_script_hash.clone(); + } + } + + if let Some(reserve_initial_incentive_amount) = reserve_initial_incentive_amount_opt { + if reserve_initial_incentive_amount == reserve_settings.mutable_settings.initial_incentive { + reserve_initial_incentive_amount_opt = None; + log::info!( + "Reserve initial incentive amount is already set to {}.", + reserve_initial_incentive_amount + ); + } else { + reserve_settings.mutable_settings.initial_incentive = reserve_initial_incentive_amount; + } + } + + if total_accrued_function_script_hash_opt.is_none() + && reserve_initial_incentive_amount_opt.is_none() + { + return Err(anyhow::anyhow!("Nothing to update.")); + } let tx_to_evaluate = update_reserve_settings_tx( &reserve_settings, diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index e2f26876f..eea6980bc 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -338,8 +338,8 @@ async fn run_update_reserve_settings_management< reserve::update_settings::update_reserve_settings( genesis_utxo, GOVERNANCE_AUTHORITY_PAYMENT_KEY.0, - UPDATED_TOTAL_ACCRUED_FUNCTION_SCRIPT_HASH, - UPDATED_INITIAL_INCENTIVE, + Some(UPDATED_TOTAL_ACCRUED_FUNCTION_SCRIPT_HASH), + Some(UPDATED_INITIAL_INCENTIVE), client, &FixedDelayRetries::new(Duration::from_millis(500), 100), ) diff --git a/toolkit/utils/ogmios-client/src/types.rs b/toolkit/utils/ogmios-client/src/types.rs index 3e18bd35e..562bcb7ce 100644 --- a/toolkit/utils/ogmios-client/src/types.rs +++ b/toolkit/utils/ogmios-client/src/types.rs @@ -80,7 +80,7 @@ impl From<[u8; 32]> for DatumHash { impl std::fmt::Debug for DatumHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("DatumHash").field("bytes", &hex::encode(&self.bytes)).finish() + f.debug_struct("DatumHash").field("bytes", &hex::encode(self.bytes)).finish() } } From 58c493d648ee99acffd1d729a754432c5ca6d88a Mon Sep 17 00:00:00 2001 From: Krisztian Pinter Date: Fri, 17 Jan 2025 11:18:10 +0100 Subject: [PATCH 3/7] address comments --- toolkit/offchain/src/csl.rs | 1 - toolkit/offchain/src/reserve/create.rs | 3 +- toolkit/offchain/src/reserve/deposit.rs | 3 +- toolkit/offchain/src/reserve/mod.rs | 124 ++++++++++-------- .../offchain/src/reserve/update_settings.rs | 27 ++-- toolkit/offchain/tests/integration_tests.rs | 9 +- 6 files changed, 82 insertions(+), 85 deletions(-) diff --git a/toolkit/offchain/src/csl.rs b/toolkit/offchain/src/csl.rs index 090949838..103e0fde9 100644 --- a/toolkit/offchain/src/csl.rs +++ b/toolkit/offchain/src/csl.rs @@ -88,7 +88,6 @@ pub(crate) fn get_builder_config( .ref_script_coins_per_byte(&convert_reference_script_costs( &protocol_parameters.min_fee_reference_scripts.clone(), )?) - .deduplicate_explicit_ref_inputs_with_regular_inputs(true) .build() } diff --git a/toolkit/offchain/src/reserve/create.rs b/toolkit/offchain/src/reserve/create.rs index 6c37a9704..9887e879f 100644 --- a/toolkit/offchain/src/reserve/create.rs +++ b/toolkit/offchain/src/reserve/create.rs @@ -24,7 +24,6 @@ use crate::{ TransactionOutputAmountBuilderExt, }, init_governance::{get_governance_data, GovernanceData}, - reserve::get_reserve_data, scripts_data::ReserveScripts, }; use anyhow::anyhow; @@ -55,7 +54,7 @@ pub async fn create_reserve_utxo< ) -> anyhow::Result { let ctx = TransactionContext::for_payment_key(payment_key, client).await?; let governance = get_governance_data(genesis_utxo, client).await?; - let reserve = get_reserve_data(genesis_utxo, &ctx, client).await?; + let reserve = ReserveData::get(genesis_utxo, &ctx, client).await?; let tx_to_evaluate = create_reserve_tx( ¶meters, diff --git a/toolkit/offchain/src/reserve/deposit.rs b/toolkit/offchain/src/reserve/deposit.rs index 8f66357a4..fa99ff17b 100644 --- a/toolkit/offchain/src/reserve/deposit.rs +++ b/toolkit/offchain/src/reserve/deposit.rs @@ -24,7 +24,6 @@ use crate::{ TransactionOutputAmountBuilderExt, }, init_governance::{get_governance_data, GovernanceData}, - reserve::get_reserve_data, scripts_data::ReserveScripts, }; use anyhow::anyhow; @@ -60,7 +59,7 @@ pub async fn deposit_to_reserve< ) -> anyhow::Result { let ctx = TransactionContext::for_payment_key(payment_key, client).await?; let governance = get_governance_data(genesis_utxo, client).await?; - let reserve = get_reserve_data(genesis_utxo, &ctx, client).await?; + let reserve = ReserveData::get(genesis_utxo, &ctx, client).await?; let utxo = get_utxo_with_tokens(&reserve.scripts, ¶meters.token, &ctx, client).await? .ok_or_else(||anyhow!("There are no UTXOs in the Reserve Validator address that contain token Reserve Auth Policy Token. Has Reserve been created already?"))?; diff --git a/toolkit/offchain/src/reserve/mod.rs b/toolkit/offchain/src/reserve/mod.rs index 9467415e4..27e0a4cc9 100644 --- a/toolkit/offchain/src/reserve/mod.rs +++ b/toolkit/offchain/src/reserve/mod.rs @@ -26,70 +26,82 @@ pub struct ReserveData { pub illiquid_circulation_supply_validator_version_utxo: OgmiosUtxo, } +#[derive(Clone, Debug)] +pub struct ReserveUtxo { + pub reserve_utxo: OgmiosUtxo, + pub reserve_settings: ReserveDatum, +} + impl ReserveData { - pub async fn get_reserve_settings< + pub async fn get( + genesis_utxo: UtxoId, + ctx: &TransactionContext, + client: &T, + ) -> Result { + let version_oracle = scripts_data::version_oracle(genesis_utxo, ctx.network)?; + let auth_policy_version_utxo = + find_script_utxo( + raw_scripts::ScriptId::ReserveAuthPolicy as u32, + &version_oracle, + ctx, + client, + ) + .await? + .ok_or_else(|| { + anyhow!("Reserve Auth Version Utxo not found, is the Reserve Token Management initialized?") + })?; + let validator_version_utxo = find_script_utxo( + raw_scripts::ScriptId::ReserveValidator as u32, + &version_oracle, + ctx, + client, + ) + .await? + .ok_or_else(|| { + anyhow!("Reserve Validator Version Utxo not found, is the Reserve Token Management initialized?") + })?; + let illiquid_circulation_supply_validator_version_utxo = find_script_utxo( + raw_scripts::ScriptId::IlliquidCirculationSupplyValidator as u32, + &version_oracle, + ctx, + client, + ) + .await? + .ok_or_else(|| { + anyhow!("Illiquid Circulation Supply Validator Version Utxo not found, is the Reserve Token Management initialized?") + })?; + let scripts = scripts_data::reserve_scripts(genesis_utxo, ctx.network)?; + Ok(ReserveData { + scripts, + auth_policy_version_utxo, + validator_version_utxo, + illiquid_circulation_supply_validator_version_utxo, + }) + } + + pub async fn get_reserve_utxo< T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, >( &self, ctx: &TransactionContext, client: &T, - ) -> Result, anyhow::Error> { + ) -> Result { let validator_address = self.scripts.validator.address(ctx.network).to_bech32(None)?; let validator_utxos = client.query_utxos(&[validator_address]).await?; - Ok(validator_utxos.into_iter().find_map(|utxo| { - utxo.clone() - .datum - .and_then(|d| PlutusData::from_bytes(d.bytes).ok()) - .and_then(|d| ReserveDatum::try_from(d).ok()) - .map(|d| (utxo, d)) - })) - } -} + let (reserve_utxo, reserve_settings) = validator_utxos + .into_iter() + .find_map(|utxo| { + utxo.clone() + .datum + .and_then(|d| PlutusData::from_bytes(d.bytes).ok()) + .and_then(|d| ReserveDatum::try_from(d).ok()) + .map(|d| (utxo, d)) + }) + .ok_or_else(|| { + anyhow!("Reserve Utxo not found, is the Reserve Token Management initialized?") + })?; -pub async fn get_reserve_data< - T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, ->( - genesis_utxo: UtxoId, - ctx: &TransactionContext, - client: &T, -) -> Result { - let version_oracle = scripts_data::version_oracle(genesis_utxo, ctx.network)?; - let auth_policy_version_utxo = find_script_utxo( - raw_scripts::ScriptId::ReserveAuthPolicy as u32, - &version_oracle, - ctx, - client, - ) - .await? - .ok_or_else(|| { - anyhow!("Reserve Auth Version Utxo not found, is the Reserve Token Management initialized?") - })?; - let validator_version_utxo = find_script_utxo( - raw_scripts::ScriptId::ReserveValidator as u32, - &version_oracle, - ctx, - client, - ) - .await? - .ok_or_else(|| { - anyhow!("Reserve Validator Version Utxo not found, is the Reserve Token Management initialized?") - })?; - let illiquid_circulation_supply_validator_version_utxo = find_script_utxo( - raw_scripts::ScriptId::IlliquidCirculationSupplyValidator as u32, - &version_oracle, - ctx, - client, - ) - .await? - .ok_or_else(|| { - anyhow!("Illiquid Circulation Supply Validator Version Utxo not found, is the Reserve Token Management initialized?") - })?; - let scripts = scripts_data::reserve_scripts(genesis_utxo, ctx.network)?; - Ok(ReserveData { - scripts, - auth_policy_version_utxo, - validator_version_utxo, - illiquid_circulation_supply_validator_version_utxo, - }) + Ok(ReserveUtxo { reserve_utxo, reserve_settings }) + } } diff --git a/toolkit/offchain/src/reserve/update_settings.rs b/toolkit/offchain/src/reserve/update_settings.rs index 4ac3d25f9..442c5fce7 100644 --- a/toolkit/offchain/src/reserve/update_settings.rs +++ b/toolkit/offchain/src/reserve/update_settings.rs @@ -16,8 +16,8 @@ //! * Reserve Validator Version Utxo //! * Governance Policy Script -use super::get_reserve_data; use super::ReserveData; +use crate::reserve::ReserveUtxo; use crate::{ await_tx::AwaitTx, csl::*, init_governance::get_governance_data, init_governance::GovernanceData, @@ -42,14 +42,12 @@ pub async fn update_reserve_settings< mut reserve_initial_incentive_amount_opt: Option, client: &T, await_tx: &A, -) -> anyhow::Result { +) -> anyhow::Result> { let ctx = TransactionContext::for_payment_key(payment_key, client).await?; let governance = get_governance_data(genesis_utxo, client).await?; - let reserve = get_reserve_data(genesis_utxo, &ctx, client).await?; - let (reserve_utxo, mut reserve_settings) = reserve - .get_reserve_settings(&ctx, client) - .await? - .expect("reserve utxo must exist"); + let reserve = ReserveData::get(genesis_utxo, &ctx, client).await?; + let ReserveUtxo { reserve_utxo, mut reserve_settings } = + reserve.get_reserve_utxo(&ctx, client).await?; if let Some(total_accrued_function_script_hash) = total_accrued_function_script_hash_opt.clone() { @@ -82,7 +80,8 @@ pub async fn update_reserve_settings< if total_accrued_function_script_hash_opt.is_none() && reserve_initial_incentive_amount_opt.is_none() { - return Err(anyhow::anyhow!("Nothing to update.")); + log::info!("Nothing to update."); + return Ok(None); } let tx_to_evaluate = update_reserve_settings_tx( @@ -129,7 +128,7 @@ pub async fn update_reserve_settings< let tx_id = res.transaction.id; log::info!("Update Reserve Settings transaction submitted: {}", hex::encode(tx_id)); await_tx.await_tx_output(client, UtxoId::new(tx_id, 0)).await?; - Ok(McTxHash(tx_id)) + Ok(Some(McTxHash(tx_id))) } fn update_reserve_settings_tx( @@ -167,12 +166,10 @@ fn update_reserve_settings_tx( tx_builder.set_inputs(&inputs); } - // mint new settings { let amount_builder = TransactionOutputBuilder::new() .with_address(&reserve.scripts.validator.address(ctx.network)) .with_plutus_data(&(datum.clone().into())) - .with_script_ref(&ScriptRef::new_plutus_script(&reserve.scripts.validator.to_csl())) .next()?; let mut val = reserve_utxo.value.to_csl()?; let output = amount_builder.with_value(&val).build()?; @@ -198,17 +195,9 @@ fn update_reserve_settings_tx( &reserve.illiquid_circulation_supply_validator_version_utxo.to_csl_tx_input(), reserve.scripts.illiquid_circulation_supply_validator.bytes.len(), ); - tx_builder.add_script_reference_input( &reserve.auth_policy_version_utxo.to_csl_tx_input(), reserve.scripts.auth_policy.bytes.len(), ); - tx_builder.add_script_reference_input( - &reserve.validator_version_utxo.to_csl_tx_input(), - reserve.scripts.validator.bytes.len(), - ); - - tx_builder.add_required_signer(&ctx.payment_key_hash()); - tx_builder.balance_update_and_build(ctx) } diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index eea6980bc..8ec46caa0 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -334,7 +334,7 @@ async fn run_update_reserve_settings_management< >( genesis_utxo: UtxoId, client: &T, -) -> McTxHash { +) -> Option { reserve::update_settings::update_reserve_settings( genesis_utxo, GOVERNANCE_AUTHORITY_PAYMENT_KEY.0, @@ -446,13 +446,12 @@ async fn assert_mutable_settings_eq Date: Fri, 17 Jan 2025 12:46:18 +0100 Subject: [PATCH 4/7] review comments --- toolkit/offchain/src/csl.rs | 4 +- toolkit/offchain/src/lib.rs | 2 +- toolkit/offchain/src/reserve/mod.rs | 22 ++++--- toolkit/offchain/src/scripts_data.rs | 8 +-- toolkit/offchain/tests/integration_tests.rs | 67 +++++++++++++++++---- 5 files changed, 73 insertions(+), 30 deletions(-) diff --git a/toolkit/offchain/src/csl.rs b/toolkit/offchain/src/csl.rs index 103e0fde9..9ca2f8fa1 100644 --- a/toolkit/offchain/src/csl.rs +++ b/toolkit/offchain/src/csl.rs @@ -289,7 +289,7 @@ impl MainchainPrivateKeyExt for MainchainPrivateKey { } } -pub struct TransactionContext { +pub(crate) struct TransactionContext { /// This key is added as required signer and used to sign the transaction. pub(crate) payment_key: PrivateKey, /// Used to pay for the transaction fees and uncovered transaction inputs @@ -302,7 +302,7 @@ pub struct TransactionContext { impl TransactionContext { /// Gets `TransactionContext`, having UTXOs for the given payment key and the network configuration, /// required to perform most of the partner-chains smart contract operations. - pub async fn for_payment_key( + pub(crate) async fn for_payment_key( payment_signing_key: [u8; 32], client: &C, ) -> Result { diff --git a/toolkit/offchain/src/lib.rs b/toolkit/offchain/src/lib.rs index c423409bc..b441cb0ea 100644 --- a/toolkit/offchain/src/lib.rs +++ b/toolkit/offchain/src/lib.rs @@ -13,7 +13,7 @@ pub mod ogmios_mock; /// Supports Permissioned Candidates upsert pub mod permissioned_candidates; /// Utilities for handling Plutus script data -mod plutus_script; +pub mod plutus_script; /// Supports candidate registration pub mod register; pub mod reserve; diff --git a/toolkit/offchain/src/reserve/mod.rs b/toolkit/offchain/src/reserve/mod.rs index 27e0a4cc9..a7877cd3f 100644 --- a/toolkit/offchain/src/reserve/mod.rs +++ b/toolkit/offchain/src/reserve/mod.rs @@ -19,21 +19,23 @@ pub mod init; pub mod update_settings; #[derive(Clone, Debug)] -pub struct ReserveData { - pub scripts: scripts_data::ReserveScripts, - pub auth_policy_version_utxo: OgmiosUtxo, - pub validator_version_utxo: OgmiosUtxo, - pub illiquid_circulation_supply_validator_version_utxo: OgmiosUtxo, +pub(crate) struct ReserveData { + pub(crate) scripts: scripts_data::ReserveScripts, + pub(crate) auth_policy_version_utxo: OgmiosUtxo, + pub(crate) validator_version_utxo: OgmiosUtxo, + pub(crate) illiquid_circulation_supply_validator_version_utxo: OgmiosUtxo, } #[derive(Clone, Debug)] -pub struct ReserveUtxo { - pub reserve_utxo: OgmiosUtxo, - pub reserve_settings: ReserveDatum, +pub(crate) struct ReserveUtxo { + pub(crate) reserve_utxo: OgmiosUtxo, + pub(crate) reserve_settings: ReserveDatum, } impl ReserveData { - pub async fn get( + pub(crate) async fn get< + T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, + >( genesis_utxo: UtxoId, ctx: &TransactionContext, client: &T, @@ -79,7 +81,7 @@ impl ReserveData { }) } - pub async fn get_reserve_utxo< + pub(crate) async fn get_reserve_utxo< T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId, >( &self, diff --git a/toolkit/offchain/src/scripts_data.rs b/toolkit/offchain/src/scripts_data.rs index 8cad15d89..c12caa1cd 100644 --- a/toolkit/offchain/src/scripts_data.rs +++ b/toolkit/offchain/src/scripts_data.rs @@ -212,10 +212,10 @@ pub(crate) fn registered_candidates_scripts( } #[derive(Clone, Debug)] -pub struct ReserveScripts { - pub validator: PlutusScript, - pub auth_policy: PlutusScript, - pub illiquid_circulation_supply_validator: PlutusScript, +pub(crate) struct ReserveScripts { + pub(crate) validator: PlutusScript, + pub(crate) auth_policy: PlutusScript, + pub(crate) illiquid_circulation_supply_validator: PlutusScript, } pub(crate) fn reserve_scripts( diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index 8ec46caa0..b9cf47b67 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -6,22 +6,24 @@ //! In case of change to the supported cardano-node or ogmios, //! it should be updated accordingly and pushed to the registry. -use cardano_serialization_lib::NetworkIdKind; +use cardano_serialization_lib::{Language, NetworkIdKind}; use hex_literal::hex; use ogmios_client::{ jsonrpsee::{client_for_url, OgmiosClients}, query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId}, query_network::QueryNetwork, transactions::Transactions, + types::OgmiosUtxo, }; use partner_chains_cardano_offchain::{ await_tx::{AwaitTx, FixedDelayRetries}, - csl::TransactionContext, + csl::NetworkTypeExt, d_param, init_governance, permissioned_candidates, + plutus_script::PlutusScript, register::Register, reserve, scripts_data, update_governance, }; -use partner_chains_plutus_data::reserve::ReserveMutableSettings; +use partner_chains_plutus_data::reserve::{ReserveDatum, ReserveMutableSettings}; use sidechain_domain::{ AdaBasedStaking, AssetId, AssetName, AuraPublicKey, CandidateRegistration, DParameter, GrandpaPublicKey, MainchainAddressHash, MainchainPrivateKey, MainchainPublicKey, @@ -443,19 +445,58 @@ async fn assert_mutable_settings_eq( + genesis_utxo: UtxoId, + client: &T, +) -> (OgmiosUtxo, ReserveDatum) { + let network = client.shelley_genesis_configuration().await.unwrap().network.to_csl(); + + let validator_script = PlutusScript::from_wrapped_cbor( + raw_scripts::VERSION_ORACLE_VALIDATOR, + Language::new_plutus_v2(), + ) + .unwrap() + .apply_data(genesis_utxo) + .unwrap(); + let policy_script = PlutusScript::from_wrapped_cbor( + raw_scripts::VERSION_ORACLE_POLICY, + Language::new_plutus_v2(), + ) + .unwrap() + .apply_data(genesis_utxo) + .unwrap() + .apply_uplc_data(validator_script.address_data(network).unwrap()) + .unwrap(); + + let validator = + PlutusScript::from_wrapped_cbor(raw_scripts::RESERVE_VALIDATOR, Language::new_plutus_v2()) + .unwrap() + .apply_uplc_data(uplc::PlutusData::BoundedBytes( + policy_script.script_hash().to_vec().into(), + )) + .unwrap(); + + let validator_address = validator.address(network).to_bech32(None).unwrap(); + let validator_utxos = client.query_utxos(&[validator_address]).await.unwrap(); + + validator_utxos + .into_iter() + .find_map(|utxo| { + utxo.clone() + .datum + .and_then(|d| cardano_serialization_lib::PlutusData::from_bytes(d.bytes).ok()) + .and_then(|d| ReserveDatum::try_from(d).ok()) + .map(|d| (utxo, d)) + }) + .unwrap() +} From 862e8681425f63bf9de4059c956692e3457e526b Mon Sep 17 00:00:00 2001 From: Krisztian Pinter Date: Fri, 17 Jan 2025 14:59:11 +0100 Subject: [PATCH 5/7] review comments --- toolkit/offchain/src/reserve/mod.rs | 9 ++++ toolkit/offchain/src/scripts_data.rs | 2 +- toolkit/offchain/tests/integration_tests.rs | 48 +++++++-------------- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/toolkit/offchain/src/reserve/mod.rs b/toolkit/offchain/src/reserve/mod.rs index a7877cd3f..730dfd4af 100644 --- a/toolkit/offchain/src/reserve/mod.rs +++ b/toolkit/offchain/src/reserve/mod.rs @@ -94,6 +94,15 @@ impl ReserveData { let (reserve_utxo, reserve_settings) = validator_utxos .into_iter() .find_map(|utxo| { + let reserve_auth_policy_id = self.scripts.auth_policy.policy_id().0; + let reserve_auth_asset_name: Vec = Vec::new(); + let auth_token = + utxo.value.native_tokens.get(&reserve_auth_policy_id).and_then(|assets| { + assets.iter().find(|asset| { + asset.name == reserve_auth_asset_name && asset.amount == 1i128 + }) + }); + auth_token?; utxo.clone() .datum .and_then(|d| PlutusData::from_bytes(d.bytes).ok()) diff --git a/toolkit/offchain/src/scripts_data.rs b/toolkit/offchain/src/scripts_data.rs index c12caa1cd..4ff421e54 100644 --- a/toolkit/offchain/src/scripts_data.rs +++ b/toolkit/offchain/src/scripts_data.rs @@ -99,7 +99,7 @@ pub fn get_scripts_data( pub async fn get_scripts_data_with_ogmios( genesis_utxo: UtxoId, - client: impl QueryNetwork, + client: &impl QueryNetwork, ) -> anyhow::Result { let network = client.shelley_genesis_configuration().await?.network.to_csl(); get_scripts_data(genesis_utxo, network) diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index b9cf47b67..4b0ff713d 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -6,7 +6,7 @@ //! In case of change to the supported cardano-node or ogmios, //! it should be updated accordingly and pushed to the registry. -use cardano_serialization_lib::{Language, NetworkIdKind}; +use cardano_serialization_lib::NetworkIdKind; use hex_literal::hex; use ogmios_client::{ jsonrpsee::{client_for_url, OgmiosClients}, @@ -17,9 +17,7 @@ use ogmios_client::{ }; use partner_chains_cardano_offchain::{ await_tx::{AwaitTx, FixedDelayRetries}, - csl::NetworkTypeExt, d_param, init_governance, permissioned_candidates, - plutus_script::PlutusScript, register::Register, reserve, scripts_data, update_governance, }; @@ -455,43 +453,29 @@ async fn assert_mutable_settings_eq( +async fn get_reserve_utxo< + T: QueryLedgerState + ogmios_client::OgmiosClient + ogmios_client::query_network::QueryNetwork, +>( genesis_utxo: UtxoId, client: &T, ) -> (OgmiosUtxo, ReserveDatum) { - let network = client.shelley_genesis_configuration().await.unwrap().network.to_csl(); - - let validator_script = PlutusScript::from_wrapped_cbor( - raw_scripts::VERSION_ORACLE_VALIDATOR, - Language::new_plutus_v2(), - ) - .unwrap() - .apply_data(genesis_utxo) - .unwrap(); - let policy_script = PlutusScript::from_wrapped_cbor( - raw_scripts::VERSION_ORACLE_POLICY, - Language::new_plutus_v2(), - ) - .unwrap() - .apply_data(genesis_utxo) - .unwrap() - .apply_uplc_data(validator_script.address_data(network).unwrap()) - .unwrap(); - - let validator = - PlutusScript::from_wrapped_cbor(raw_scripts::RESERVE_VALIDATOR, Language::new_plutus_v2()) - .unwrap() - .apply_uplc_data(uplc::PlutusData::BoundedBytes( - policy_script.script_hash().to_vec().into(), - )) - .unwrap(); - - let validator_address = validator.address(network).to_bech32(None).unwrap(); + let scripts_data = + scripts_data::get_scripts_data_with_ogmios(genesis_utxo, client).await.unwrap(); + let validator_address = scripts_data.addresses.reserve_validator; let validator_utxos = client.query_utxos(&[validator_address]).await.unwrap(); validator_utxos .into_iter() .find_map(|utxo| { + let reserve_auth_policy_id = scripts_data.policy_ids.reserve_auth.0; + let reserve_auth_asset_name: Vec = Vec::new(); + let auth_token = + utxo.value.native_tokens.get(&reserve_auth_policy_id).and_then(|assets| { + assets.iter().find(|asset| { + asset.name == reserve_auth_asset_name && asset.amount == 1i128 + }) + }); + auth_token?; utxo.clone() .datum .and_then(|d| cardano_serialization_lib::PlutusData::from_bytes(d.bytes).ok()) From 6926f746cae3e60a4c85667bf2a7a6b63f7d15b0 Mon Sep 17 00:00:00 2001 From: Krisztian Pinter Date: Fri, 17 Jan 2025 15:51:01 +0100 Subject: [PATCH 6/7] cleanup --- toolkit/offchain/src/lib.rs | 2 +- toolkit/offchain/src/reserve/mod.rs | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/toolkit/offchain/src/lib.rs b/toolkit/offchain/src/lib.rs index b441cb0ea..c423409bc 100644 --- a/toolkit/offchain/src/lib.rs +++ b/toolkit/offchain/src/lib.rs @@ -13,7 +13,7 @@ pub mod ogmios_mock; /// Supports Permissioned Candidates upsert pub mod permissioned_candidates; /// Utilities for handling Plutus script data -pub mod plutus_script; +mod plutus_script; /// Supports candidate registration pub mod register; pub mod reserve; diff --git a/toolkit/offchain/src/reserve/mod.rs b/toolkit/offchain/src/reserve/mod.rs index 730dfd4af..ee72f98c9 100644 --- a/toolkit/offchain/src/reserve/mod.rs +++ b/toolkit/offchain/src/reserve/mod.rs @@ -1,5 +1,6 @@ //! All smart-contracts related to Rewards Token Reserve Management +use crate::csl::OgmiosUtxoExt; use crate::{csl::TransactionContext, scripts_data}; use anyhow::anyhow; use cardano_serialization_lib::PlutusData; @@ -11,7 +12,7 @@ use ogmios_client::{ types::OgmiosUtxo, }; use partner_chains_plutus_data::reserve::ReserveDatum; -use sidechain_domain::UtxoId; +use sidechain_domain::{AssetId, AssetName, UtxoId}; pub mod create; pub mod deposit; @@ -91,18 +92,17 @@ impl ReserveData { let validator_address = self.scripts.validator.address(ctx.network).to_bech32(None)?; let validator_utxos = client.query_utxos(&[validator_address]).await?; + let auth_token_asset_id = AssetId { + policy_id: self.scripts.auth_policy.policy_id(), + asset_name: AssetName::from_hex_unsafe(""), + }; + let (reserve_utxo, reserve_settings) = validator_utxos .into_iter() .find_map(|utxo| { - let reserve_auth_policy_id = self.scripts.auth_policy.policy_id().0; - let reserve_auth_asset_name: Vec = Vec::new(); - let auth_token = - utxo.value.native_tokens.get(&reserve_auth_policy_id).and_then(|assets| { - assets.iter().find(|asset| { - asset.name == reserve_auth_asset_name && asset.amount == 1i128 - }) - }); - auth_token?; + if utxo.get_asset_amount(&auth_token_asset_id) != 1i128 { + return None; + } utxo.clone() .datum .and_then(|d| PlutusData::from_bytes(d.bytes).ok()) From ff02a63124402d3ed385194d306feed02a14322e Mon Sep 17 00:00:00 2001 From: Krisztian Pinter Date: Mon, 20 Jan 2025 10:55:41 +0100 Subject: [PATCH 7/7] fix --- toolkit/cli/smart-contracts-commands/src/get_scripts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/cli/smart-contracts-commands/src/get_scripts.rs b/toolkit/cli/smart-contracts-commands/src/get_scripts.rs index b2c2298ba..eec2369a8 100644 --- a/toolkit/cli/smart-contracts-commands/src/get_scripts.rs +++ b/toolkit/cli/smart-contracts-commands/src/get_scripts.rs @@ -14,7 +14,7 @@ pub struct GetScripts { impl GetScripts { pub async fn execute(self) -> crate::CmdResult<()> { let client = client_for_url(&self.common_arguments.ogmios_url).await?; - let scripts_data = get_scripts_data_with_ogmios(self.genesis_utxo, client).await?; + let scripts_data = get_scripts_data_with_ogmios(self.genesis_utxo, &client).await?; let json = serde_json::to_string_pretty(&scripts_data)?;