Skip to content

Commit 965ebc7

Browse files
authored
Merge pull request #618 from Emurgo/evgenii/datum_change
Datum change
2 parents 64573f6 + 7f95255 commit 965ebc7

File tree

7 files changed

+173
-10
lines changed

7 files changed

+173
-10
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cardano-serialization-lib",
3-
"version": "11.4.0",
3+
"version": "11.4.1-beta.1",
44
"description": "(De)serialization functions for the Cardano blockchain along with related utility functions",
55
"scripts": {
66
"rust:build-nodejs": "(rimraf ./rust/pkg && cd rust; wasm-pack build --target=nodejs; cd ..; npm run js:ts-json-gen; cd rust; wasm-pack pack) && npm run js:flowgen",

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cardano-serialization-lib"
3-
version = "11.4.0"
3+
version = "11.4.1-beta.1"
44
edition = "2018"
55
authors = ["EMURGO"]
66
license = "MIT"

rust/json-gen/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/pkg/cardano_serialization_lib.js.flow

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4695,6 +4695,33 @@ declare export class OperationalCert {
46954695
sigma: Ed25519Signature
46964696
): OperationalCert;
46974697
}
4698+
/**
4699+
*/
4700+
declare export class OutputDatum {
4701+
free(): void;
4702+
4703+
/**
4704+
* @param {DataHash} data_hash
4705+
* @returns {OutputDatum}
4706+
*/
4707+
static new_data_hash(data_hash: DataHash): OutputDatum;
4708+
4709+
/**
4710+
* @param {PlutusData} data
4711+
* @returns {OutputDatum}
4712+
*/
4713+
static new_data(data: PlutusData): OutputDatum;
4714+
4715+
/**
4716+
* @returns {DataHash | void}
4717+
*/
4718+
data_hash(): DataHash | void;
4719+
4720+
/**
4721+
* @returns {PlutusData | void}
4722+
*/
4723+
data(): PlutusData | void;
4724+
}
46984725
/**
46994726
*/
47004727
declare export class PlutusData {
@@ -8591,6 +8618,16 @@ declare export class TransactionBuilder {
85918618
*/
85928619
add_change_if_needed(address: Address): boolean;
85938620

8621+
/**
8622+
* @param {Address} address
8623+
* @param {OutputDatum} plutus_data
8624+
* @returns {boolean}
8625+
*/
8626+
add_change_if_needed_with_datum(
8627+
address: Address,
8628+
plutus_data: OutputDatum
8629+
): boolean;
8630+
85948631
/**
85958632
* This method will calculate the script hash data
85968633
* using the plutus datums and redeemers already present in the builder

rust/src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,6 +2145,36 @@ pub enum DataOption {
21452145
Data(PlutusData),
21462146
}
21472147

2148+
#[wasm_bindgen]
2149+
#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd )]
2150+
pub struct OutputDatum(pub(crate) DataOption);
2151+
2152+
#[wasm_bindgen]
2153+
impl OutputDatum {
2154+
2155+
pub fn new_data_hash(data_hash: &DataHash) -> Self {
2156+
Self(DataOption::DataHash(data_hash.clone()))
2157+
}
2158+
2159+
pub fn new_data(data: &PlutusData) -> Self {
2160+
Self(DataOption::Data(data.clone()))
2161+
}
2162+
2163+
pub fn data_hash(&self) -> Option<DataHash> {
2164+
match &self.0 {
2165+
DataOption::DataHash(data_hash) => Some(data_hash.clone()),
2166+
_ => None,
2167+
}
2168+
}
2169+
2170+
pub fn data(&self) -> Option<PlutusData> {
2171+
match &self.0 {
2172+
DataOption::Data(data) => Some(data.clone()),
2173+
_ => None,
2174+
}
2175+
}
2176+
}
2177+
21482178
#[wasm_bindgen]
21492179
#[derive(
21502180
Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,

rust/src/tx_builder.rs

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,26 @@ impl TransactionBuilder {
13381338
/// Editing inputs, outputs, mint, etc. after change been calculated
13391339
/// might cause a mismatch in calculated fee versus the required fee
13401340
pub fn add_change_if_needed(&mut self, address: &Address) -> Result<bool, JsError> {
1341+
self.add_change_if_needed_with_optional_script_and_datum(address, None, None)
1342+
}
1343+
1344+
pub fn add_change_if_needed_with_datum(&mut self,
1345+
address: &Address,
1346+
plutus_data: &OutputDatum)
1347+
-> Result<bool, JsError>
1348+
{
1349+
self.add_change_if_needed_with_optional_script_and_datum(
1350+
address,
1351+
Some(plutus_data.0.clone()),
1352+
None)
1353+
}
1354+
1355+
1356+
fn add_change_if_needed_with_optional_script_and_datum(&mut self, address: &Address,
1357+
plutus_data: Option<DataOption>,
1358+
script_ref: Option<ScriptRef>)
1359+
-> Result<bool, JsError>
1360+
{
13411361
let fee = match &self.fee {
13421362
None => self.min_fee(),
13431363
// generating the change output involves changing the fee
@@ -1348,11 +1368,6 @@ impl TransactionBuilder {
13481368
}
13491369
}?;
13501370

1351-
// note: can't add plutus data or data hash and script to change
1352-
// because we don't know how many change outputs will need to be created
1353-
let plutus_data: Option<DataOption> = None;
1354-
let script_ref: Option<ScriptRef> = None;
1355-
13561371
let input_total = self.get_total_input()?;
13571372
let output_total = self.get_total_output()?;
13581373

@@ -1941,7 +1956,7 @@ impl TransactionBuilder {
19411956
mod tests {
19421957
use super::output_builder::TransactionOutputBuilder;
19431958
use super::*;
1944-
use crate::fakes::{fake_base_address, fake_bytes_32, fake_key_hash, fake_policy_id, fake_tx_hash, fake_tx_input, fake_tx_input2, fake_value, fake_value2};
1959+
use crate::fakes::{fake_base_address, fake_bytes_32, fake_data_hash, fake_key_hash, fake_policy_id, fake_tx_hash, fake_tx_input, fake_tx_input2, fake_value, fake_value2};
19451960
use crate::tx_builder_constants::TxBuilderConstants;
19461961
use fees::*;
19471962
use crate::tx_builder::tx_inputs_builder::{InputsWithScriptWitness, InputWithScriptWitness, PlutusScriptSource};
@@ -2154,6 +2169,87 @@ mod tests {
21542169
let _final_tx = tx_builder.build(); // just test that it doesn't throw
21552170
}
21562171

2172+
#[test]
2173+
fn build_tx_with_change_with_datum() {
2174+
let mut tx_builder = create_default_tx_builder();
2175+
let spend = root_key_15()
2176+
.derive(harden(1852))
2177+
.derive(harden(1815))
2178+
.derive(harden(0))
2179+
.derive(0)
2180+
.derive(0)
2181+
.to_public();
2182+
let change_key = root_key_15()
2183+
.derive(harden(1852))
2184+
.derive(harden(1815))
2185+
.derive(harden(0))
2186+
.derive(1)
2187+
.derive(0)
2188+
.to_public();
2189+
let stake = root_key_15()
2190+
.derive(harden(1852))
2191+
.derive(harden(1815))
2192+
.derive(harden(0))
2193+
.derive(2)
2194+
.derive(0)
2195+
.to_public();
2196+
2197+
let spend_cred = StakeCredential::from_keyhash(&spend.to_raw_key().hash());
2198+
let stake_cred = StakeCredential::from_keyhash(&stake.to_raw_key().hash());
2199+
let addr_net_0 = BaseAddress::new(
2200+
NetworkInfo::testnet().network_id(),
2201+
&spend_cred,
2202+
&stake_cred,
2203+
)
2204+
.to_address();
2205+
tx_builder.add_key_input(
2206+
&spend.to_raw_key().hash(),
2207+
&TransactionInput::new(&genesis_id(), 0),
2208+
&Value::new(&to_bignum(1_000_000)),
2209+
);
2210+
tx_builder
2211+
.add_output(
2212+
&TransactionOutputBuilder::new()
2213+
.with_address(&addr_net_0)
2214+
.next()
2215+
.unwrap()
2216+
.with_coin(&to_bignum(222))
2217+
.build()
2218+
.unwrap(),
2219+
)
2220+
.unwrap();
2221+
tx_builder.set_ttl(1000);
2222+
2223+
let datum_hash = fake_data_hash(20);
2224+
let data_option = OutputDatum::new_data_hash(&datum_hash);
2225+
let (_, script_hash) = plutus_script_and_hash(15);
2226+
let change_cred = StakeCredential::from_scripthash(&script_hash);
2227+
let change_addr = BaseAddress::new(
2228+
NetworkInfo::testnet().network_id(),
2229+
&change_cred,
2230+
&stake_cred,
2231+
)
2232+
.to_address();
2233+
let added_change = tx_builder.add_change_if_needed_with_datum(&change_addr, &data_option);
2234+
assert!(added_change.unwrap());
2235+
assert_eq!(tx_builder.outputs.len(), 2);
2236+
assert_eq!(
2237+
tx_builder
2238+
.get_explicit_input()
2239+
.unwrap()
2240+
.checked_add(&tx_builder.get_implicit_input().unwrap())
2241+
.unwrap(),
2242+
tx_builder
2243+
.get_explicit_output()
2244+
.unwrap()
2245+
.checked_add(&Value::new(&tx_builder.get_fee_if_set().unwrap()))
2246+
.unwrap()
2247+
);
2248+
assert_eq!(tx_builder.full_size().unwrap(), 319);
2249+
assert_eq!(tx_builder.output_sizes(), vec![62, 99]);
2250+
let _final_tx = tx_builder.build(); // just test that it doesn't throw
2251+
}
2252+
21572253
#[test]
21582254
fn build_tx_without_change() {
21592255
let mut tx_builder = create_default_tx_builder();

0 commit comments

Comments
 (0)