Skip to content

Commit 2e04521

Browse files
authored
Merge pull request #514 from Emurgo/evgenii/ref_inputs_builder
Added ref inputs support to inputs builder
2 parents 053ea34 + aeff1e4 commit 2e04521

File tree

6 files changed

+307
-156
lines changed

6 files changed

+307
-156
lines changed

rust/pkg/cardano_serialization_lib.js.flow

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,12 @@ declare export class Costmdls {
19521952
* @returns {Languages}
19531953
*/
19541954
keys(): Languages;
1955+
1956+
/**
1957+
* @param {Languages} languages
1958+
* @returns {Costmdls}
1959+
*/
1960+
retain_language_versions(languages: Languages): Costmdls;
19551961
}
19561962
/**
19571963
*/
@@ -2124,6 +2130,23 @@ declare export class DataHash {
21242130
*/
21252131
static from_hex(hex: string): DataHash;
21262132
}
2133+
/**
2134+
*/
2135+
declare export class DatumSource {
2136+
free(): void;
2137+
2138+
/**
2139+
* @param {PlutusData} datum
2140+
* @returns {DatumSource}
2141+
*/
2142+
static new(datum: PlutusData): DatumSource;
2143+
2144+
/**
2145+
* @param {TransactionInput} input
2146+
* @returns {DatumSource}
2147+
*/
2148+
static new_ref_input(input: TransactionInput): DatumSource;
2149+
}
21272150
/**
21282151
*/
21292152
declare export class Ed25519KeyHash {
@@ -4715,6 +4738,27 @@ declare export class PlutusScript {
47154738
*/
47164739
language_version(): Language;
47174740
}
4741+
/**
4742+
*/
4743+
declare export class PlutusScriptSource {
4744+
free(): void;
4745+
4746+
/**
4747+
* @param {PlutusScript} script
4748+
* @returns {PlutusScriptSource}
4749+
*/
4750+
static new(script: PlutusScript): PlutusScriptSource;
4751+
4752+
/**
4753+
* @param {ScriptHash} script_hash
4754+
* @param {TransactionInput} input
4755+
* @returns {PlutusScriptSource}
4756+
*/
4757+
static new_ref_input(
4758+
script_hash: ScriptHash,
4759+
input: TransactionInput
4760+
): PlutusScriptSource;
4761+
}
47184762
/**
47194763
*/
47204764
declare export class PlutusScripts {
@@ -4797,14 +4841,26 @@ declare export class PlutusWitness {
47974841
): PlutusWitness;
47984842

47994843
/**
4800-
* @returns {PlutusScript}
4844+
* @param {PlutusScriptSource} script
4845+
* @param {DatumSource} datum
4846+
* @param {Redeemer} redeemer
4847+
* @returns {PlutusWitness}
48014848
*/
4802-
script(): PlutusScript;
4849+
static new_with_ref(
4850+
script: PlutusScriptSource,
4851+
datum: DatumSource,
4852+
redeemer: Redeemer
4853+
): PlutusWitness;
48034854

48044855
/**
4805-
* @returns {PlutusData}
4856+
* @returns {PlutusScript | void}
4857+
*/
4858+
script(): PlutusScript | void;
4859+
4860+
/**
4861+
* @returns {PlutusData | void}
48064862
*/
4807-
datum(): PlutusData;
4863+
datum(): PlutusData | void;
48084864

48094865
/**
48104866
* @returns {Redeemer}
@@ -9280,6 +9336,11 @@ declare export class TxInputsBuilder {
92809336
*/
92819337
add_required_plutus_input_scripts(scripts: PlutusWitnesses): number;
92829338

9339+
/**
9340+
* @returns {TransactionInputs}
9341+
*/
9342+
get_ref_inputs(): TransactionInputs;
9343+
92839344
/**
92849345
* Returns a copy of the current script input witness scripts in the builder
92859346
* @returns {NativeScripts | void}
@@ -10336,6 +10397,7 @@ export interface ProtocolVersionJSON {
1033610397
major: number;
1033710398
minor: number;
1033810399
}
10400+
export type ProtocolVersionsJSON = ProtocolVersionJSON[];
1033910401
export type PublicKeyJSON = string;
1034010402
export interface RedeemerJSON {
1034110403
data: PlutusDataJSON;

rust/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ impl TransactionBody {
568568

569569
#[wasm_bindgen]
570570
#[derive(
571-
Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
571+
Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, serde::Serialize, serde::Deserialize, JsonSchema,
572572
)]
573573
pub struct TransactionInput {
574574
transaction_id: TransactionHash,

rust/src/plutus.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,9 @@ impl Costmdls {
386386
serializer.finalize()
387387
}
388388

389-
pub(crate) fn retain_language_versions(&self, languages: Vec<Language>) -> Costmdls {
389+
pub fn retain_language_versions(&self, languages: &Languages) -> Costmdls {
390390
let mut result = Costmdls::new();
391-
for lang in languages {
391+
for lang in &languages.0 {
392392
match self.get(&lang) {
393393
Some(costmodel) => { result.insert(&lang, &costmodel); },
394394
_ => {}
@@ -2362,7 +2362,7 @@ mod tests {
23622362
let hash = hash_script_data(
23632363
&redeemers,
23642364
&TxBuilderConstants::plutus_vasil_cost_models()
2365-
.retain_language_versions(vec![Language::new_plutus_v1()]),
2365+
.retain_language_versions(&Languages(vec![Language::new_plutus_v1()])),
23662366
Some(datums),
23672367
);
23682368
assert_eq!(hex::encode(hash.to_bytes()), "e6129f50a866d19d95bc9c95ee87b57a9e695c05d92ba2746141b03c15cf5f70");

rust/src/tx_builder.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ pub struct TransactionBuilder {
355355
required_signers: Ed25519KeyHashes,
356356
collateral_return: Option<TransactionOutput>,
357357
total_collateral: Option<Coin>,
358-
reference_inputs: TransactionInputs,
358+
reference_inputs: HashSet<TransactionInput>,
359359
}
360360

361361
#[wasm_bindgen]
@@ -757,7 +757,7 @@ impl TransactionBuilder {
757757
}
758758

759759
pub fn add_reference_input(&mut self, reference_input: &TransactionInput) {
760-
self.reference_inputs.add(reference_input);
760+
self.reference_inputs.insert(reference_input.clone());
761761
}
762762

763763
/// We have to know what kind of inputs these are to know what kind of mock witnesses to create since
@@ -1201,12 +1201,18 @@ impl TransactionBuilder {
12011201
required_signers: Ed25519KeyHashes::new(),
12021202
collateral_return: None,
12031203
total_collateral: None,
1204-
reference_inputs: TransactionInputs::new(),
1204+
reference_inputs: HashSet::new(),
12051205
}
12061206
}
12071207

12081208
pub fn get_reference_inputs(&self) -> TransactionInputs {
1209-
self.reference_inputs.clone()
1209+
let mut inputs = self.reference_inputs.clone();
1210+
for input in self.inputs.get_ref_inputs().0 {
1211+
inputs.insert(input);
1212+
}
1213+
1214+
let vec_inputs = inputs.into_iter().collect();
1215+
TransactionInputs(vec_inputs)
12101216
}
12111217

12121218
/// does not include refunds or withdrawals
@@ -1709,7 +1715,7 @@ impl TransactionBuilder {
17091715
network_id: None,
17101716
collateral_return: self.collateral_return.clone(),
17111717
total_collateral: self.total_collateral.clone(),
1712-
reference_inputs: self.reference_inputs.to_option(),
1718+
reference_inputs: self.get_reference_inputs().to_option(),
17131719
};
17141720
// we must build a tx with fake data (of correct size) to check the final Transaction size
17151721
let full_tx = fake_full_tx(self, built)?;

rust/src/tx_builder/tx_inputs_builder.rs

Lines changed: 102 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,95 @@ pub(crate) struct TxBuilderInput {
77
pub(crate) amount: Value, // we need to keep track of the amount in the inputs for input selection
88
}
99

10+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
11+
pub enum PlutusScriptSourceEnum {
12+
Script(PlutusScript),
13+
RefInput(TransactionInput, ScriptHash),
14+
}
15+
16+
impl PlutusScriptSourceEnum {
17+
pub fn script_hash(&self) -> ScriptHash {
18+
match self {
19+
PlutusScriptSourceEnum::Script(script) => script.hash(),
20+
PlutusScriptSourceEnum::RefInput(_, script_hash) => script_hash.clone(),
21+
}
22+
}
23+
}
24+
1025
#[wasm_bindgen]
11-
#[derive(
12-
Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
13-
)]
26+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
27+
pub struct PlutusScriptSource(PlutusScriptSourceEnum);
28+
29+
#[wasm_bindgen]
30+
impl PlutusScriptSource {
31+
pub fn new(script: &PlutusScript) -> Self {
32+
Self(PlutusScriptSourceEnum::Script(script.clone()))
33+
}
34+
35+
pub fn new_ref_input(script_hash: &ScriptHash, input: &TransactionInput) -> Self {
36+
Self(PlutusScriptSourceEnum::RefInput(input.clone(), script_hash.clone()))
37+
}
38+
}
39+
40+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
41+
pub enum DatumSourceEnum {
42+
Datum(PlutusData),
43+
RefInput(TransactionInput),
44+
}
45+
46+
#[wasm_bindgen]
47+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
48+
pub struct DatumSource(DatumSourceEnum);
49+
50+
#[wasm_bindgen]
51+
impl DatumSource {
52+
pub fn new(datum: &PlutusData) -> Self {
53+
Self(DatumSourceEnum::Datum(datum.clone()))
54+
}
55+
56+
pub fn new_ref_input(input: &TransactionInput) -> Self {
57+
Self(DatumSourceEnum::RefInput(input.clone()))
58+
}
59+
}
60+
61+
#[wasm_bindgen]
62+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
1463
pub struct PlutusWitness {
15-
script: PlutusScript,
16-
datum: PlutusData,
64+
script: PlutusScriptSourceEnum,
65+
datum: DatumSourceEnum,
1766
redeemer: Redeemer,
1867
}
1968

2069
#[wasm_bindgen]
2170
impl PlutusWitness {
2271
pub fn new(script: &PlutusScript, datum: &PlutusData, redeemer: &Redeemer) -> Self {
2372
Self {
24-
script: script.clone(),
25-
datum: datum.clone(),
73+
script: PlutusScriptSourceEnum::Script(script.clone()),
74+
datum: DatumSourceEnum::Datum(datum.clone()),
75+
redeemer: redeemer.clone(),
76+
}
77+
}
78+
79+
pub fn new_with_ref(script: &PlutusScriptSource, datum: &DatumSource, redeemer: &Redeemer) -> Self {
80+
Self {
81+
script: script.0.clone(),
82+
datum: datum.0.clone(),
2683
redeemer: redeemer.clone(),
2784
}
2885
}
2986

30-
pub fn script(&self) -> PlutusScript {
31-
self.script.clone()
87+
pub fn script(&self) -> Option<PlutusScript> {
88+
match &self.script {
89+
PlutusScriptSourceEnum::Script(script) => Some(script.clone()),
90+
_ => None,
91+
}
3292
}
3393

34-
pub fn datum(&self) -> PlutusData {
35-
self.datum.clone()
94+
pub fn datum(&self) -> Option<PlutusData> {
95+
match &self.datum {
96+
DatumSourceEnum::Datum(datum) => Some(datum.clone()),
97+
_ => None,
98+
}
3699
}
37100

38101
pub fn redeemer(&self) -> Redeemer {
@@ -49,9 +112,7 @@ impl PlutusWitness {
49112
}
50113

51114
#[wasm_bindgen]
52-
#[derive(
53-
Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
54-
)]
115+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
55116
pub struct PlutusWitnesses(pub(crate) Vec<PlutusWitness>);
56117

57118
#[wasm_bindgen]
@@ -77,8 +138,12 @@ impl PlutusWitnesses {
77138
let mut d = PlutusList::new();
78139
let mut r = Redeemers::new();
79140
self.0.iter().for_each(|w| {
80-
s.add(&w.script);
81-
d.add(&w.datum);
141+
if let PlutusScriptSourceEnum::Script(script) = &w.script {
142+
s.add(script);
143+
}
144+
if let DatumSourceEnum::Datum(datum) = &w.datum {
145+
d.add(datum);
146+
}
82147
r.add(&w.redeemer);
83148
});
84149
(s, d, r)
@@ -87,12 +152,7 @@ impl PlutusWitnesses {
87152

88153
impl From<Vec<PlutusWitness>> for PlutusWitnesses {
89154
fn from(scripts: Vec<PlutusWitness>) -> Self {
90-
scripts
91-
.iter()
92-
.fold(PlutusWitnesses::new(), |mut scripts, s| {
93-
scripts.add(s);
94-
scripts
95-
})
155+
Self(scripts)
96156
}
97157
}
98158

@@ -200,7 +260,8 @@ impl TxInputsBuilder {
200260
input: &TransactionInput,
201261
amount: &Value,
202262
) {
203-
let hash = witness.script.hash();
263+
let hash = witness.script.script_hash();
264+
204265
self.add_script_input(&hash, input, amount);
205266
self.input_types.scripts.insert(
206267
hash,
@@ -306,7 +367,7 @@ impl TxInputsBuilder {
306367
/// Use `.count_missing_input_scripts` to find the number of still missing scripts
307368
pub fn add_required_plutus_input_scripts(&mut self, scripts: &PlutusWitnesses) -> usize {
308369
scripts.0.iter().for_each(|s: &PlutusWitness| {
309-
let hash = s.script.hash();
370+
let hash = s.script.script_hash();
310371
if self.input_types.scripts.contains_key(&hash) {
311372
self.input_types.scripts.insert(
312373
hash,
@@ -317,6 +378,23 @@ impl TxInputsBuilder {
317378
self.count_missing_input_scripts()
318379
}
319380

381+
pub fn get_ref_inputs(&self) -> TransactionInputs {
382+
let mut inputs = Vec::new();
383+
for wintess in self.input_types.scripts.iter()
384+
.filter_map(|(_, wit)| wit.as_ref() ) {
385+
if let ScriptWitnessType::PlutusScriptWitness(plutus_witness) = wintess {
386+
if let DatumSourceEnum::RefInput(input) = &plutus_witness.datum {
387+
inputs.push(input.clone());
388+
}
389+
if let PlutusScriptSourceEnum::RefInput(input, _) = &plutus_witness.script {
390+
inputs.push(input.clone());
391+
}
392+
}
393+
}
394+
395+
TransactionInputs(inputs)
396+
}
397+
320398
/// Returns a copy of the current script input witness scripts in the builder
321399
pub fn get_native_input_scripts(&self) -> Option<NativeScripts> {
322400
let mut scripts = NativeScripts::new();

0 commit comments

Comments
 (0)