Skip to content

Commit

Permalink
fix redeemer ex units indexing
Browse files Browse the repository at this point in the history
  • Loading branch information
jankun4 committed Dec 12, 2024
1 parent c329a99 commit 1eed2bc
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 78 deletions.
71 changes: 43 additions & 28 deletions toolkit/offchain/src/csl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use ogmios_client::{
types::{OgmiosUtxo, OgmiosValue},
};
use sidechain_domain::NetworkType;
use std::collections::HashMap;

pub(crate) fn plutus_script_hash(script_bytes: &[u8], language: LanguageKind) -> [u8; 28] {
// Before hashing the script, we need to prepend with byte denoting the language.
Expand Down Expand Up @@ -168,31 +169,38 @@ pub(crate) fn get_first_validator_budget(

#[derive(Debug, Clone, PartialEq)]
pub struct ScriptExUnits {
pub mint_ex_units: Vec<ExUnits>,
pub spend_ex_units: Vec<ExUnits>,
pub mint_ex_units: HashMap<u32, ExUnits>,
pub spend_ex_units: HashMap<u32, ExUnits>,
}

impl ScriptExUnits {
pub fn new() -> Self {
ScriptExUnits { mint_ex_units: Vec::new(), spend_ex_units: Vec::new() }
ScriptExUnits { mint_ex_units: HashMap::new(), spend_ex_units: HashMap::new() }
}
pub fn with_mint_ex_units(self, mint_ex_units: Vec<ExUnits>) -> Self {
pub fn with_mint_ex_units(self, mint_ex_units: HashMap<u32, ExUnits>) -> Self {
Self { mint_ex_units, ..self }
}
pub fn with_spend_ex_units(self, spend_ex_units: Vec<ExUnits>) -> Self {
pub fn with_spend_ex_units(self, spend_ex_units: HashMap<u32, ExUnits>) -> Self {
Self { spend_ex_units, ..self }
}
}

pub(crate) fn get_validator_budgets(
mut responses: Vec<OgmiosEvaluateTransactionResponse>,
responses: Vec<OgmiosEvaluateTransactionResponse>,
) -> Result<ScriptExUnits, JsError> {
responses.sort_by_key(|r| r.validator.index);
let (mint_ex_units, spend_ex_units) = responses
.into_iter()
.partition::<Vec<_>, _>(|response| response.validator.purpose == "mint");
let mint_ex_units = mint_ex_units.into_iter().map(ex_units_from_response).collect();
let spend_ex_units = spend_ex_units.into_iter().map(ex_units_from_response).collect();
let mut spend_ex_units = HashMap::new();
let mut mint_ex_units = HashMap::new();
for r in responses {
println!("Validator: {:?}", r);
match r.validator.purpose.as_str() {
"mint" => mint_ex_units.insert(r.validator.index, ex_units_from_response(r)),
"spend" => spend_ex_units.insert(r.validator.index, ex_units_from_response(r)),
_ => return Err(JsError::from_str(&format!(
"Internal error: unexpected validator purpose '{}'",
r.validator.purpose
))),
};
};

Ok(ScriptExUnits { mint_ex_units, spend_ex_units })
}
Expand Down Expand Up @@ -331,6 +339,7 @@ pub(crate) trait TransactionBuilderExt {
&mut self,
script: &PlutusScript,
ex_units: ExUnits,
script_index: u32,
) -> Result<(), JsError>;

/// Adds minting of 1 token (with empty asset name) for the given script using reference input
Expand All @@ -339,6 +348,7 @@ pub(crate) trait TransactionBuilderExt {
script: &PlutusScript,
ref_input: &TransactionInput,
ex_units: ExUnits,
script_index: u32,
) -> Result<(), JsError>;

/// Sets fields required by the most of partner-chains smart contract transactions.
Expand Down Expand Up @@ -399,6 +409,7 @@ impl TransactionBuilderExt for TransactionBuilder {
&mut self,
script: &PlutusScript,
ex_units: ExUnits,
script_index: u32,
) -> Result<(), JsError> {
let mut mint_builder = self.get_mint_builder().unwrap_or(MintBuilder::new());

Expand All @@ -407,7 +418,7 @@ impl TransactionBuilderExt for TransactionBuilder {
&validator_source,
&Redeemer::new(
&RedeemerTag::new_mint(),
&0u32.into(),
&script_index.into(),
&PlutusData::new_empty_constr_plutus_data(&0u32.into()),
&ex_units,
),
Expand All @@ -422,6 +433,7 @@ impl TransactionBuilderExt for TransactionBuilder {
script: &PlutusScript,
ref_input: &TransactionInput,
ex_units: ExUnits,
script_index: u32,
) -> Result<(), JsError> {
let mut mint_builder = self.get_mint_builder().unwrap_or(MintBuilder::new());

Expand All @@ -435,7 +447,7 @@ impl TransactionBuilderExt for TransactionBuilder {
&validator_source,
&Redeemer::new(
&RedeemerTag::new_mint(),
&0u32.into(),
&script_index.into(),
&PlutusData::new_empty_constr_plutus_data(&0u32.into()),
&ex_units,
),
Expand Down Expand Up @@ -510,6 +522,7 @@ pub(crate) trait InputsBuilderExt: Sized {
utxo: &OgmiosUtxo,
script: &PlutusScript,
ex_units: ExUnits,
script_index: u32,
) -> Result<(), JsError>;

/// Adds ogmios inputs to the tx inputs builder.
Expand All @@ -525,6 +538,7 @@ impl InputsBuilderExt for TxInputsBuilder {
utxo: &OgmiosUtxo,
script: &PlutusScript,
ex_units: ExUnits,
script_index: u32,
) -> Result<(), JsError> {
let input = utxo.to_csl_tx_input();
let amount = convert_value(&utxo.value)?;
Expand All @@ -533,7 +547,7 @@ impl InputsBuilderExt for TxInputsBuilder {
&Redeemer::new(
&RedeemerTag::new_spend(),
// CSL will set redeemer index for the index of script input after sorting transaction inputs
&0u32.into(),
&script_index.into(),
&PlutusData::new_empty_constr_plutus_data(&0u32.into()),
&ex_units,
),
Expand Down Expand Up @@ -704,33 +718,33 @@ mod tests {
fn get_validator_budgets_works() {
let result = get_validator_budgets(vec![
OgmiosEvaluateTransactionResponse {
validator: OgmiosValidatorIndex::new(1, "mint"),
validator: OgmiosValidatorIndex::new(0, "mint"),
budget: OgmiosBudget::new(11, 21),
},
OgmiosEvaluateTransactionResponse {
validator: OgmiosValidatorIndex::new(0, "spend"),
budget: OgmiosBudget::new(10, 20),
budget: OgmiosBudget::new(12, 22),
},
OgmiosEvaluateTransactionResponse {
validator: OgmiosValidatorIndex::new(3, "mint"),
validator: OgmiosValidatorIndex::new(1, "mint"),
budget: OgmiosBudget::new(13, 23),
},
OgmiosEvaluateTransactionResponse {
validator: OgmiosValidatorIndex::new(2, "spend"),
budget: OgmiosBudget::new(12, 22),
validator: OgmiosValidatorIndex::new(1, "spend"),
budget: OgmiosBudget::new(14, 24),
},
])
.expect("Should succeed");

let expected = ScriptExUnits {
mint_ex_units: vec![
ExUnits::new(&11u64.into(), &21u64.into()),
ExUnits::new(&13u64.into(), &23u64.into()),
],
spend_ex_units: vec![
ExUnits::new(&10u64.into(), &20u64.into()),
ExUnits::new(&12u64.into(), &22u64.into()),
],
mint_ex_units: HashMap::from([
(0, ExUnits::new(&11u64.into(), &21u64.into())),
(1, ExUnits::new(&13u64.into(), &23u64.into())),
]),
spend_ex_units: HashMap::from([
(0, ExUnits::new(&12u64.into(), &22u64.into())),
(1, ExUnits::new(&14u64.into(), &24u64.into())),
]),
};

assert_eq!(result, expected);
Expand Down Expand Up @@ -769,6 +783,7 @@ mod prop_tests {
.add_mint_one_script_token(
&test_policy(),
ExUnits::new(&BigNum::zero(), &BigNum::zero()),
0,
)
.unwrap();
tx_builder
Expand Down
52 changes: 30 additions & 22 deletions toolkit/offchain/src/d_param/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -120,11 +121,11 @@ 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![],
mint_ex_units: HashMap::from([
(0, ExUnits::new(&0u64.into(), &0u64.into())),
(1, ExUnits::new(&0u64.into(), &0u64.into())),
]),
spend_ex_units: HashMap::new(),
};

let gov_utxo = crate::init_governance::get_governance_utxo(genesis_utxo, client)
Expand All @@ -146,14 +147,13 @@ 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 ex_units = get_validator_budgets(evaluate_response)?;
let tx = mint_d_param_token_tx(
validator,
policy,
d_parameter,
&ctx,
mint_witness_ex_units,
ex_units,
gov_utxo,
)?;
let signed_tx = ctx.sign(&tx).to_bytes();
Expand Down Expand Up @@ -182,8 +182,8 @@ where
C: Transactions,
{
let zero_ex_units = ScriptExUnits {
mint_ex_units: vec![ExUnits::new(&0u64.into(), &0u64.into())],
spend_ex_units: vec![ExUnits::new(&0u64.into(), &0u64.into())],
mint_ex_units: HashMap::from([(0, ExUnits::new(&0u64.into(), &0u64.into()))]),
spend_ex_units: HashMap::from([(0, ExUnits::new(&0u64.into(), &0u64.into()))]),
};

let gov_utxo = crate::init_governance::get_governance_utxo(genesis_utxo, client)
Expand All @@ -206,15 +206,15 @@ where
hex::encode(tx.to_bytes())
)
})?;
let spend_ex_units = get_validator_budgets(evaluate_response)?;
let ex_units = get_validator_budgets(evaluate_response)?;

let tx = update_d_param_tx(
validator,
policy,
d_parameter,
current_utxo,
&ctx,
spend_ex_units,
ex_units,
gov_utxo.clone(),
)?;
let signed_tx = ctx.sign(&tx).to_bytes();
Expand All @@ -235,7 +235,7 @@ fn mint_d_param_token_tx(
policy: &PlutusScript,
d_parameter: &DParameter,
ctx: &TransactionContext,
mut ex_units: ScriptExUnits,
ex_units: ScriptExUnits,
gov_utxo: OgmiosUtxo,
) -> Result<Transaction, JsError> {
let mut tx_builder = TransactionBuilder::new(&get_builder_config(ctx)?);
Expand All @@ -244,8 +244,10 @@ fn mint_d_param_token_tx(
policy,
ex_units
.mint_ex_units
.pop()
.unwrap_or_else(|| panic!("Mint ex units not found")),
.get(&0)
.unwrap_or_else(|| panic!("Mint ex units not found"))
.clone(),
0,
)?;
tx_builder.add_output_with_one_script_token(
validator,
Expand All @@ -268,8 +270,10 @@ fn mint_d_param_token_tx(
&gov_tx_input,
ex_units
.mint_ex_units
.pop()
.unwrap_or_else(|| panic!("Mint ex units not found")),
.get(&1)
.unwrap_or_else(|| panic!("Mint ex units not found"))
.clone(),
1,
)?;

let tx_hash = TransactionHash::from_bytes(gov_utxo.transaction.id.into())?;
Expand All @@ -285,7 +289,7 @@ fn update_d_param_tx(
d_parameter: &DParameter,
script_utxo: &OgmiosUtxo,
ctx: &TransactionContext,
mut ex_units: ScriptExUnits,
ex_units: ScriptExUnits,
gov_utxo: OgmiosUtxo,
) -> Result<Transaction, JsError> {
let config = crate::csl::get_builder_config(ctx)?;
Expand All @@ -297,8 +301,10 @@ fn update_d_param_tx(
validator,
ex_units
.spend_ex_units
.pop()
.unwrap_or_else(|| panic!("Spend ex units not found")),
.get(&0)
.unwrap_or_else(|| panic!("Spend ex units not found"))
.clone(),
0,
)?;
tx_builder.set_inputs(&inputs);

Expand All @@ -323,8 +329,10 @@ fn update_d_param_tx(
&gov_tx_input,
ex_units
.mint_ex_units
.pop()
.unwrap_or_else(|| panic!("Mint ex units not found")),
.get(&0)
.unwrap_or_else(|| panic!("Mint ex units not found"))
.clone(),
0,
)?;

let tx_hash = TransactionHash::from_bytes(gov_utxo.transaction.id.into())?;
Expand Down
7 changes: 4 additions & 3 deletions toolkit/offchain/src/d_param/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use ogmios_client::types::{Asset as OgmiosAsset, OgmiosTx, OgmiosUtxo, OgmiosVal
use ogmios_client::types::{OgmiosScript, PlutusScript};
use partner_chains_plutus_data::d_param::d_parameter_to_plutus_data;
use sidechain_domain::DParameter;
use std::collections::HashMap;

mod mint_tx {
use super::*;
Expand All @@ -21,7 +22,7 @@ mod mint_tx {
ExUnits::new(&10000u32.into(), &200u32.into())
}
fn ex_units() -> ScriptExUnits {
ScriptExUnits::new().with_mint_ex_units(vec![mint_ex_units(), mint_ex_units()])
ScriptExUnits::new().with_mint_ex_units(HashMap::from([(0, mint_ex_units()), (1, mint_ex_units())]))
}
fn mint_d_param_tx() -> Transaction {
mint_d_param_token_tx(
Expand Down Expand Up @@ -185,8 +186,8 @@ mod update_d_parameter {
}
fn ex_units() -> ScriptExUnits {
ScriptExUnits::new()
.with_spend_ex_units(vec![spend_ex_units()])
.with_mint_ex_units(vec![mint_ex_units()])
.with_spend_ex_units(HashMap::from([(0, spend_ex_units())]))
.with_mint_ex_units(HashMap::from([(0, mint_ex_units())]))
}

fn update_d_param_tx() -> Transaction {
Expand Down
Loading

0 comments on commit 1eed2bc

Please sign in to comment.