Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix redeemer ex units indexing #325

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading