Skip to content

Commit 2d625f2

Browse files
committed
Added TxBuilderConstants.plutus_default_cost_models plus tests
1 parent 91184ec commit 2d625f2

File tree

5 files changed

+152
-2
lines changed

5 files changed

+152
-2
lines changed

rust/pkg/cardano_serialization_lib.js.flow

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6336,6 +6336,16 @@ declare export class TransactionWitnessSets {
63366336
*/
63376337
add(elem: TransactionWitnessSet): void;
63386338
}
6339+
/**
6340+
*/
6341+
declare export class TxBuilderConstants {
6342+
free(): void;
6343+
6344+
/**
6345+
* @returns {Costmdls}
6346+
*/
6347+
static plutus_default_cost_models(): Costmdls;
6348+
}
63396349
/**
63406350
*/
63416351
declare export class URL {

rust/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub mod output_builder;
4848
pub mod plutus;
4949
pub mod serialization;
5050
pub mod tx_builder;
51+
pub mod tx_builder_constants;
5152
pub mod typed_bytes;
5253
pub mod emip3;
5354
#[macro_use]

rust/src/plutus.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ impl CostModel {
161161
}
162162
}
163163

164+
impl From<[i32; 166]> for CostModel {
165+
fn from(values: [i32; 166]) -> Self {
166+
CostModel(values.iter().map(|x| { Int::new_i32(*x).clone() }).collect())
167+
}
168+
}
169+
164170
#[wasm_bindgen]
165171
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
166172
pub struct Costmdls(std::collections::BTreeMap<Language, CostModel>);
@@ -498,6 +504,12 @@ impl PlutusList {
498504
}
499505
}
500506

507+
impl From<Vec<PlutusData>> for PlutusList {
508+
fn from(elems: Vec<PlutusData>) -> Self {
509+
Self { elems, definite_encoding: None }
510+
}
511+
}
512+
501513
#[wasm_bindgen]
502514
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
503515
pub struct Redeemer {
@@ -609,6 +621,12 @@ impl Redeemers {
609621
}
610622
}
611623

624+
impl From<Vec<Redeemer>> for Redeemers {
625+
fn from(values: Vec<Redeemer>) -> Self {
626+
Self(values)
627+
}
628+
}
629+
612630
#[wasm_bindgen]
613631
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
614632
pub struct Strings(Vec<String>);

rust/src/tx_builder.rs

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,7 @@ impl TransactionBuilder {
16081608
mod tests {
16091609
use super::*;
16101610
use fees::*;
1611+
use crate::tx_builder_constants::TxBuilderConstants;
16111612
use super::output_builder::{TransactionOutputBuilder};
16121613

16131614
const MAX_VALUE_SIZE: u32 = 4000;
@@ -1626,11 +1627,11 @@ mod tests {
16261627
}
16271628

16281629
fn fake_bytes(x: u8) -> Vec<u8> {
1629-
vec![x, 239, 181, 120, 142, 135, 19, 200, 68, 223, 211, 43, 46, 145, 222, 30, 48, 159, 239, 255, 213, 85, 248, 39, 204, 158, 225, 100]
1630+
vec![x, 239, 181, 120, 142, 135, 19, 200, 68, 223, 211, 43, 46, 145, 222, 30, 48, 159, 239, 255, 213, 85, 248, 39, 204, 158, 225, 100, 1, 2, 3, 4]
16301631
}
16311632

16321633
fn fake_key_hash(x: u8) -> Ed25519KeyHash {
1633-
Ed25519KeyHash::from_bytes(fake_bytes(x)).unwrap()
1634+
Ed25519KeyHash::from_bytes((&fake_bytes(x)[0..28]).to_vec()).unwrap()
16341635
}
16351636

16361637
fn harden(index: u32) -> u32 {
@@ -4797,5 +4798,82 @@ mod tests {
47974798
assert_eq!(redeems.get(0), redeemer1);
47984799
assert_eq!(redeems.get(1), redeemer2);
47994800
}
4801+
4802+
#[test]
4803+
fn test_existing_plutus_scripts_require_data_hash() {
4804+
let mut tx_builder = create_reallistic_tx_builder();
4805+
tx_builder.set_fee(&to_bignum(42));
4806+
let (script1, _) = plutus_script_and_hash(0);
4807+
let datum = PlutusData::new_bytes(fake_bytes(1));
4808+
let redeemer_datum = PlutusData::new_bytes(fake_bytes(2));
4809+
let redeemer = Redeemer::new(
4810+
&RedeemerTag::new_spend(),
4811+
&to_bignum(0),
4812+
&redeemer_datum,
4813+
&ExUnits::new(&to_bignum(1), &to_bignum(2)),
4814+
);
4815+
tx_builder.add_plutus_script_input(
4816+
&PlutusWitness::new(&script1, &datum, &redeemer),
4817+
&TransactionInput::new(&genesis_id(), 0),
4818+
&Value::new(&to_bignum(1_000_000)),
4819+
);
4820+
4821+
// Using SAFE `.build_tx`
4822+
let res = tx_builder.build_tx();
4823+
assert!(res.is_err());
4824+
if let Err(e) = res {
4825+
assert!(e.as_string().unwrap().contains("script data hash"));
4826+
}
4827+
4828+
// Setting script data hash removes the error
4829+
tx_builder.set_script_data_hash(
4830+
&ScriptDataHash::from_bytes(fake_bytes(42)).unwrap(),
4831+
);
4832+
// Using SAFE `.build_tx`
4833+
let res2 = tx_builder.build_tx();
4834+
assert!(res2.is_ok());
4835+
4836+
// Removing script data hash will cause error again
4837+
tx_builder.remove_script_data_hash();
4838+
// Using SAFE `.build_tx`
4839+
let res3 = tx_builder.build_tx();
4840+
assert!(res3.is_err());
4841+
}
4842+
4843+
#[test]
4844+
fn test_calc_script_hash_data() {
4845+
let mut tx_builder = create_reallistic_tx_builder();
4846+
tx_builder.set_fee(&to_bignum(42));
4847+
let (script1, _) = plutus_script_and_hash(0);
4848+
let datum = PlutusData::new_bytes(fake_bytes(1));
4849+
let redeemer_datum = PlutusData::new_bytes(fake_bytes(2));
4850+
let redeemer = Redeemer::new(
4851+
&RedeemerTag::new_spend(),
4852+
&to_bignum(0),
4853+
&redeemer_datum,
4854+
&ExUnits::new(&to_bignum(1), &to_bignum(2)),
4855+
);
4856+
tx_builder.add_plutus_script_input(
4857+
&PlutusWitness::new(&script1, &datum, &redeemer),
4858+
&TransactionInput::new(&genesis_id(), 0),
4859+
&Value::new(&to_bignum(1_000_000)),
4860+
);
4861+
4862+
// Setting script data hash removes the error
4863+
tx_builder.calc_script_data_hash(
4864+
&TxBuilderConstants::plutus_default_cost_models(),
4865+
);
4866+
4867+
// Using SAFE `.build_tx`
4868+
let res2 = tx_builder.build_tx();
4869+
assert!(res2.is_ok());
4870+
4871+
let data_hash = hash_script_data(
4872+
&Redeemers::from(vec![redeemer.clone()]),
4873+
&TxBuilderConstants::plutus_default_cost_models(),
4874+
Some(PlutusList::from(vec![datum])),
4875+
);
4876+
assert_eq!(tx_builder.script_data_hash.unwrap(), data_hash);
4877+
}
48004878
}
48014879

rust/src/tx_builder_constants.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use super::*;
2+
use crate::Epoch;
3+
use crate::plutus::{Costmdls, CostModel, Language};
4+
5+
// The first element is the cost model, which is an array of 166 operations costs, ordered by asc operaion names.
6+
// The second value is the pre-calculated `language_views_encoding` value required for the script hash creation.
7+
// The cost-model values are taken from the genesis block - https://github.com/input-output-hk/cardano-node/blob/master/configuration/cardano/mainnet-alonzo-genesis.json#L26-L195
8+
// The keys on the genesis block object (operation names) are sorted plain alphabetically.
9+
const PLUTUS_DEFAULT_COST_MODELS: [([i32; 166], &str); 1] = [
10+
(
11+
[197209, 0, 1, 1, 396231, 621, 0, 1, 150000, 1000, 0, 1, 150000, 32, 2477736, 29175, 4, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 100, 100, 29773, 100, 150000, 32, 150000, 32, 150000, 32, 150000, 1000, 0, 1, 150000, 32, 150000, 1000, 0, 8, 148000, 425507, 118, 0, 1, 1, 150000, 1000, 0, 8, 150000, 112536, 247, 1, 150000, 10000, 1, 136542, 1326, 1, 1000, 150000, 1000, 1, 150000, 32, 150000, 32, 150000, 32, 1, 1, 150000, 1, 150000, 4, 103599, 248, 1, 103599, 248, 1, 145276, 1366, 1, 179690, 497, 1, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 148000, 425507, 118, 0, 1, 1, 61516, 11218, 0, 1, 150000, 32, 148000, 425507, 118, 0, 1, 1, 148000, 425507, 118, 0, 1, 1, 2477736, 29175, 4, 0, 82363, 4, 150000, 5000, 0, 1, 150000, 32, 197209, 0, 1, 1, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 3345831, 1, 1],
12+
"a141005901d59f1a000302590001011a00060bc719026d00011a000249f01903e800011a000249f018201a0025cea81971f70419744d186419744d186419744d186419744d186419744d186419744d18641864186419744d18641a000249f018201a000249f018201a000249f018201a000249f01903e800011a000249f018201a000249f01903e800081a000242201a00067e2318760001011a000249f01903e800081a000249f01a0001b79818f7011a000249f0192710011a0002155e19052e011903e81a000249f01903e8011a000249f018201a000249f018201a000249f0182001011a000249f0011a000249f0041a000194af18f8011a000194af18f8011a0002377c190556011a0002bdea1901f1011a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000242201a00067e23187600010119f04c192bd200011a000249f018201a000242201a00067e2318760001011a000242201a00067e2318760001011a0025cea81971f704001a000141bb041a000249f019138800011a000249f018201a000302590001011a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a00330da70101ff",
13+
),
14+
];
15+
16+
#[wasm_bindgen]
17+
pub struct TxBuilderConstants();
18+
19+
#[wasm_bindgen]
20+
impl TxBuilderConstants {
21+
22+
pub fn plutus_default_cost_models() -> Costmdls {
23+
let mut res = Costmdls::new();
24+
res.insert(
25+
&Language::new_plutus_v1(),
26+
&CostModel::from(PLUTUS_DEFAULT_COST_MODELS[0].0),
27+
);
28+
res
29+
}
30+
}
31+
32+
#[cfg(test)]
33+
mod tests {
34+
use crate::tx_builder_constants::*;
35+
36+
#[test]
37+
pub fn cost_model_test() {
38+
assert_eq!(
39+
hex::encode(TxBuilderConstants::plutus_default_cost_models().language_views_encoding()),
40+
PLUTUS_DEFAULT_COST_MODELS[0].1,
41+
);
42+
}
43+
}

0 commit comments

Comments
 (0)