diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 715821628..ed7af6595 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,7 @@ jobs: - name: Deploy and test against local environment uses: ./.github/actions/tests/local-environment-tests with: - tag: CI + tag: CI image: ${{ secrets.ECR_REGISTRY_SECRET }}/substrate-node:${{ needs.build.outputs.sha }} sha: ${{ needs.build.outputs.sha }} tests: premerge @@ -95,7 +95,7 @@ jobs: ACTIONS_PAT: ${{ secrets.ACTIONS_PAT }} ECR_REGISTRY_SECRET: ${{ secrets.ECR_REGISTRY_SECRET }} TEST_ENVIRONMENT: local - + local-environment-tests-alert: needs: local-environment-tests if: always() && needs.local-environment-tests.result != 'skipped' @@ -226,14 +226,13 @@ jobs: pre-merge-checks-complete: if: ${{ always() && (github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == false)) }} - needs: [build, local-environment-tests, argocd-tests, devshell-tests] + needs: [build, local-environment-tests, devshell-tests] runs-on: ubuntu-latest steps: - name: Check if any needed job failed run: | - if [[ "${{ needs.build.result }}" != "success" || - "${{ needs.local-environment-tests.result }}" != "success" || - "${{ needs.argocd-tests.result }}" != "success" || + if [[ "${{ needs.build.result }}" != "success" || + "${{ needs.local-environment-tests.result }}" != "success" || "${{ needs.devshell-tests.result }}" != "success" ]]; then echo "One or more needed jobs failed." exit 1 @@ -291,7 +290,7 @@ jobs: - name: Deploy and test against local environment uses: ./.github/actions/tests/local-environment-tests with: - tag: CI + tag: CI image: ${{ secrets.ECR_REGISTRY_SECRET }}/substrate-node:${{ needs.build.outputs.sha }} sha: ${{ needs.build.outputs.sha }} tests: postmerge @@ -340,8 +339,8 @@ jobs: steps: - name: Check if any needed job failed run: | - if [[ "${{ needs.deploy-rustdoc.result }}" != "success" || - "${{ needs.upload-chain-specs.result }}" != "success" || + if [[ "${{ needs.deploy-rustdoc.result }}" != "success" || + "${{ needs.upload-chain-specs.result }}" != "success" || "${{ needs.local-environment-tests-post-merge.result }}" != "success" ]]; then echo "One or more needed jobs failed." exit 1 diff --git a/toolkit/offchain/src/d_param/mod.rs b/toolkit/offchain/src/d_param/mod.rs index f7405fea5..b42b44f97 100644 --- a/toolkit/offchain/src/d_param/mod.rs +++ b/toolkit/offchain/src/d_param/mod.rs @@ -11,7 +11,7 @@ use crate::csl::{ use crate::plutus_script::PlutusScript; use anyhow::anyhow; use cardano_serialization_lib::{ - ExUnits, JsError, PlutusData, Transaction, TransactionBuilder, TxInputsBuilder, + ExUnits, JsError, PlutusData, ScriptHash, Transaction, TransactionBuilder, TxInputsBuilder, }; use cardano_serialization_lib::{LanguageKind, TransactionHash, TransactionInput}; use ogmios_client::{ @@ -20,6 +20,7 @@ use ogmios_client::{ }; use partner_chains_plutus_data::d_param::{d_parameter_to_plutus_data, DParamDatum}; use sidechain_domain::{DParameter, McTxHash, UtxoId}; +use std::collections::HashMap; #[cfg(test)] mod tests; @@ -119,13 +120,7 @@ async fn insert_d_param( where C: Transactions, { - let zero_ex_units = ScriptExUnits { - mint_ex_units: vec![ - ExUnits::new(&0u64.into(), &0u64.into()), - ExUnits::new(&0u64.into(), &0u64.into()), - ], - spend_ex_units: vec![], - }; + let zero_ex_units = ExUnits::new(&0u64.into(), &0u64.into()); let gov_utxo = crate::init_governance::get_governance_utxo(genesis_utxo, client) .await @@ -136,9 +131,11 @@ where policy, d_parameter, &ctx, + zero_ex_units.clone(), zero_ex_units, gov_utxo.clone(), )?; + let evaluate_response = client.evaluate_transaction(&tx.to_bytes()).await.map_err(|e| { anyhow!( "Evaluate insert D-parameter transaction request failed: {}, bytes: {}", @@ -146,14 +143,26 @@ where hex::encode(tx.to_bytes()) ) })?; - let mut mint_witness_ex_units = get_validator_budgets(evaluate_response); - mint_witness_ex_units.mint_ex_units.reverse(); + + let ogmios_gov_script = + gov_utxo.clone().script.expect("Gov UTXO should have a reference script"); + let gov_policy = PlutusScript::from_ogmios(ogmios_gov_script)?; + let mint_keys = tx.body().mint().expect("insert D parameter transaction has two mints").keys(); + let script_to_index: HashMap = + vec![(mint_keys.get(0), 0), (mint_keys.get(1), 1)].into_iter().collect(); + let mint_ex_units = get_validator_budgets(evaluate_response).mint_ex_units; + let policy_idx = script_to_index.get(&policy.csl_script_hash()).unwrap().clone(); + let gov_policy_idx = script_to_index.get(&gov_policy.csl_script_hash()).unwrap().clone(); + let policy_ex_units = mint_ex_units.get(policy_idx).expect("Ogmios response should have entry for d_param policy"); + let gov_policy_ex_units = mint_ex_units.get(gov_policy_idx).expect("Ogmios response should have entry for gov policy"); + let tx = mint_d_param_token_tx( validator, policy, d_parameter, &ctx, - mint_witness_ex_units, + policy_ex_units.clone(), + gov_policy_ex_units.clone(), gov_utxo, )?; let signed_tx = ctx.sign(&tx).to_bytes(); @@ -235,18 +244,13 @@ fn mint_d_param_token_tx( policy: &PlutusScript, d_parameter: &DParameter, ctx: &TransactionContext, - mut ex_units: ScriptExUnits, + d_param_policy_ex_units: ExUnits, + gov_policy_ex_units: ExUnits, gov_utxo: OgmiosUtxo, ) -> Result { let mut tx_builder = TransactionBuilder::new(&get_builder_config(ctx)?); // The essence of transaction: mint a governance token, then mint tokena D-Param and set output with it - tx_builder.add_mint_one_script_token( - policy, - ex_units - .mint_ex_units - .pop() - .unwrap_or_else(|| panic!("Mint ex units not found")), - )?; + tx_builder.add_mint_one_script_token(policy, d_param_policy_ex_units)?; tx_builder.add_output_with_one_script_token( validator, policy, @@ -266,10 +270,7 @@ fn mint_d_param_token_tx( tx_builder.add_mint_one_script_token_using_reference_script( &gov_policy, &gov_tx_input, - ex_units - .mint_ex_units - .pop() - .unwrap_or_else(|| panic!("Mint ex units not found")), + gov_policy_ex_units, )?; tx_builder.add_script_reference_input(&gov_tx_input, gov_policy.bytes.len()); diff --git a/toolkit/offchain/src/d_param/tests.rs b/toolkit/offchain/src/d_param/tests.rs index 0d90fed13..62eaef03a 100644 --- a/toolkit/offchain/src/d_param/tests.rs +++ b/toolkit/offchain/src/d_param/tests.rs @@ -17,12 +17,14 @@ mod mint_tx { use super::*; use cardano_serialization_lib::Transaction; - fn mint_ex_units() -> ExUnits { + fn ex_units() -> ExUnits { ExUnits::new(&10000u32.into(), &200u32.into()) } - fn ex_units() -> ScriptExUnits { - ScriptExUnits::new().with_mint_ex_units(vec![mint_ex_units(), mint_ex_units()]) + + fn ex_units_2() -> ExUnits { + ExUnits::new(&20000u32.into(), &400u32.into()) } + fn mint_d_param_tx() -> Transaction { mint_d_param_token_tx( &test_validator(), @@ -30,6 +32,7 @@ mod mint_tx { &input_d_param(), &test_tx_context(), ex_units(), + ex_units_2(), governance_utxo(), ) .expect("Test transaction should be constructed without error") @@ -64,7 +67,13 @@ mod mint_tx { assert_eq!(redeemer.tag(), RedeemerTag::new_mint()); assert_eq!(redeemer.index(), 0u64.into()); assert_eq!(redeemer.data(), PlutusData::new_empty_constr_plutus_data(&0u64.into())); - assert_eq!(redeemer.ex_units(), mint_ex_units()); + assert_eq!(redeemer.ex_units(), ex_units_2()); + + let redeemer_2 = redeemers.get(1); + assert_eq!(redeemer_2.tag(), RedeemerTag::new_mint()); + assert_eq!(redeemer_2.index(), 1u64.into()); + assert_eq!(redeemer_2.data(), PlutusData::new_empty_constr_plutus_data(&0u64.into())); + assert_eq!(redeemer_2.ex_units(), ex_units()); } #[test] diff --git a/toolkit/offchain/src/plutus_script.rs b/toolkit/offchain/src/plutus_script.rs index 5e2cb5f6b..2fc397989 100644 --- a/toolkit/offchain/src/plutus_script.rs +++ b/toolkit/offchain/src/plutus_script.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Context}; use cardano_serialization_lib::{Address, LanguageKind, NetworkIdKind, PlutusData, ScriptHash}; +use ogmios_client::types::{OgmiosScript, OgmiosScript::Plutus}; use plutus::ToDatum; use sidechain_domain::PolicyId; use uplc::ast::{DeBruijn, Program}; @@ -18,6 +19,22 @@ impl PlutusScript { Self { bytes: cbor.into(), language } } + pub fn from_ogmios(ogmios_script: OgmiosScript) -> anyhow::Result { + if let Plutus(script) = ogmios_script { + let language_kind = match script.language.as_str() { + "plutus:v1" => LanguageKind::PlutusV1, + "plutus:v2" => LanguageKind::PlutusV2, + "plutus:v3" => LanguageKind::PlutusV3, + _ => { + return Err(anyhow!("Unsupported Plutus language version: {}", script.language)); + }, + }; + Ok(Self { bytes: script.cbor, language: language_kind }) + } else { + Err(anyhow!("Expected Plutus script, got something else.")) + } + } + /// This function is needed to create [PlutusScript] from scripts in [raw_scripts], /// which are encoded as a cbor byte string containing the cbor of the script /// itself. This function removes this layer of wrapping. diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index 34d7133e1..dadba930c 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -63,7 +63,6 @@ async fn init_goveranance() { () } -#[ignore = "awaiting fix for matching evaluation costs of redeemers"] #[tokio::test] async fn upsert_d_param() { let image = GenericImage::new(TEST_IMAGE, TEST_IMAGE_TAG);