Releases: Emurgo/cardano-serialization-lib
11.0.0-rc.6 "Babbage Release Candidate"
Beta release, see details: #478
11.0.0-beta.1 "Babbage Beta Candidate"
Beta release, see details: #463
11.0.0-alpha.1 "Babbage Alpha Candidate"
Alpha release, see details: #459
10.2.0 ".set_collateral"
Release PR: #447
Transaction Builder API changes
⚠️ ExUnitPrices (new optional config field)!
TransactionBuilderConfigBuilder
now has a new setter function .ex_unit_prices(ExUnitPrices)
. This property is optional and only required to calculate the fees correctly in case you are using Plutus inputs. The property is NOT required by default for backward compatibility and in case you are not using Plutus inputs at all or in case you are not calculating the fee and change automatically - it will not be required at all.
NOTE: in case you DON'T specify this parameter and you use Plutus inputs with redeemers - calling .add_inputs_from
, .fee_for_input
, .fee_for_output
, .add_change_if_needed
, or .min_fee
will fail with an error.
Handling collateral inputs with .set_inputs
and .set_collateral
All functions related to adding inputs are extracted into a new type TxInputsBuilder
, specifically:
.add_input
.add_key_input
.add_script_input
.add_native_script_input
.add_plutus_script_input
.add_bootstrap_input
.count_missing_input_scripts
.add_required_native_input_scripts
.add_required_plutus_input_scripts
.get_native_input_scripts
.get_plutus_input_scripts
The TransactionBuilder
still has all these functions for backward compatibility in relation to regular inputs, but they are deprecated now and will be removed in one of the next major versions.
Instead, there are two new function in the TransactionBuilder
:
.set_inputs(TxInputsBuilder)
.set_collateral(TxInputsBuilder)
So instead of
txBuilder.add_input(address, input, value);
The proper way of doing it from now on is:
let inputBuilder = TxInputsBuilder.new();
inputBuilder.add_input(address, input, value);
txBuilder.set_inputs(inputBuilder);
Collateral inputs
For collateral inputs there are no functions on the transaction-builder itself, they must be entirely handled though a TxInputsBuilder
instance and then added to the transaction-builder using .set_collateral
NOTE: a copy of the inputs is taken when .set_inputs
or .set_collateral
is called, so changing the TxInputsBuilder
instance after that will not affect the transaction-builder itself in any way.
NOTE: there's a new assertion happening at a .build_tx()
call - it will also now fail with an error in case the builder has some Plutus inputs, but no collateral inputs specified. The function .build_tx_unsafe()
can still be used to avoid that for whatever reason.
Required signers
There's also a single new function .add_required_signer(Ed25519KeyHash)
which adds the key into the required_signers
field of the transaction in case it's needed for some functionality.
Other new functions
.calculate_ex_units_ceil_cost(ExUnits, ExUnitPrices) -> BigNum
Given the ex-units and the ex-unit prices, calculates the coin required to pay for it. Since the ex-unit prices are specified as fractions the calculations are not as straight as just multiplying two simple numbers. So this function encapsulates all that.
.min_script_fee(Transaction, ExUnitPrices)
Is a new function to be consistent with the the previously existing .min_fee
. Given a transaction and the ex-unit prices, it checks if the transaction involves any Plutus inputs and then calculates the combined price of their ex-units.
BigInt
The BigInt
wrapper type now includes new functions: self-explanatory .add(BigInt)
, .mul(BigInt)
, and .increment()
; plus static BigInt.one()
which just returns the 1
values as bigint, plus the .div_ceil(BigInt)
function which performs the division of two bigint numbers and then CEIL rounds the result to return as also a bigint.
NOTE: that a BigInt instance is immutable and all these functions return the result as a new instance.
Plus also a new function .is_zero()
which returns a boolean.
BigNum
Static function BigNum.one()
is now available, along with the previously existing BigNum.zero()
PlutusData
New function PlutusData.new_empty_constr_plutus_data(BigNum)
creates a new instance of PlutusData
containing a ConstrPlutusData
with the specified BigNum alternative and empty parameter list.
Similar to calling:
PlutusData.new_constr_plutus_data(ConstrPlutusData.new(BigNum, PlutusList::new()))
Redeemers
New function redeemers.total_ex_units() -> ExUnits
return the sum total of all ex-units in the redeemer list.
10.1.0 "count_missing_input_scripts"
Release PR: #438
BREAKING CHANGES (Rust only, JS is not affected)
Native script hash
The function NativeScript.hash()
does NOT take any arguments now. Before it was taking the parameter ScriptHashNamespace::NativeScript
. This will break at Rust compile time if you have calls to this function in your Rust code.
The change is caused by the addition of the new function PlutusScript.hash()
which allows to produce a ScriptHash
instance from a plutus script similar to native scripts. It has proved the accepting of the ScriptHashNamespace
both unnecessary and potentially problematic. Both functions now work in a consistent way with no arguments.
In JS the existing code where the parameter is passed into the function call does NOT break at runtime, so JS is backward compatible and the removing of the argument in the existing calls is not necessary. It will break type-checkers though, but this is considered a minor issue, the highest priority is to not cause issues in runtime.
Slot type change #367 #430
The type Slot was an alias for u32
and is now replaced with two new types: Slot32
(u32
) and SlotBigNum
(BigNum
). Internally all structs are changed to contain SlotBigNum
that allows to deserialise instances with a huge slot number present with no crashing. Any getters that returned Slot
are now returning Slot32
(which is the same underlying type) and are deprecated with a new alternative getter added to receive SlotBigNum
(e.g. TransactionBody.ttl()
and new TransactionBody.ttl_bignum()
). Any functions that accepted Slot
as argument are now accepting Slot32
and are deprecated as well, and there's a new alternative function added that receives SlotBigNum
(e.g. TimelockExpiry.new(Slot32)
and new TimelockExpiry.new_timelockexpiry(SlotBigNum)
).
The change is breaking for Rust compile time, because the functions that returned Slot
are now returning Result<Slot32, JsError>
, because the underlying value can be out of bounds and might cause error when trying to convert. In JS for regular cases as long as you are using only safe instances with slot values within the regular bounds - it will not break neither runtime, not type-checkers.
Important to understand that this change is caused by the fact that there are already present cases on the blockchain when transactions contain some fields of type slot
out of the u32
bounds, so if your system is processing entire blockchain and potentially trying to parse entire transactions, including deconstructing addresses, for example - the old type Slot32
is not secure for you now and you must update your code to use the new alternative functions with SlotBigNum
, otherwise you will get a runtime crash in JS, because the old deprecated getters can now throw an out of bounds conversion error. This is relevant for any fields that can be freely defined by the tx creator - for example, transaction ttl or validity interval start.
Other changes
Burn as part of output #374
The pre-existing function TransactionBuilder.get_total_input()
is now changed to return the sum of the explicit input, the implicit input, and all the positive mint in the tx. There's now new function TransactionBuilder.get_total_output()
which returns the sum of the explicit output, any redeemed deposits (implicit output), and all the burn (negative mint) in the tx.
Script inputs support in transaction builder #436
Registering script inputs with witnesses
Two new functions available:
.add_native_script_input
- accepts aNativeScript
and the input with its value.add_plutus_script_input
- accepts aPlutusWitness
and the input with its value
The PlutusWitness
is a new available type that combines together a single PlutusScript
, single PlutusData
datum, and a single Redeemer
. The type is designed to provide the Plutus variant of a single combined witness for a separate input, similar how for a native script inputs the NativeScript
itself is all that's needed.
The two mentioned above functions will both register the input and also register the corresponding witness for it right away and will then both correctly consider the size of the witnesses when calculating the required fee and also return the witnesses as part of the result transaction when using .build_tx()
.
Registering script witnesses for already added inputs
The existing generic functions .add_input
and .add_script_input
can still be used. The only new change is that when added generically script inputs will leave a "missing script slot" which then needs to be filled before the transaction building can happen. The current number of missing scripts can be checked with the new function .count_missing_input_scripts()
which just returns the number.
To fill the missing scripts, there are two new functions:
.add_required_native_input_scripts
- takes an instance ofNativeScripts
.add_required_plutus_input_scripts
- takes an instance ofPlutusWitnesses
(which is just a collection type, similar toNativeScripts
)
These functions will compare the passed scripts with the script-hashes in the registered inputs and only take and register the relevant witness scripts. NOTE: any scripts that don't match any existing input will just be ignored, so first calling to add required scripts and then adding the input later will not work - you must first add the inputs and then call these functions to add the missing scripts (if any required). Both functions return the new number of remaining missing scripts (if zero - then all required scripts are present).
(Note once again: functions to add required scripts must ONLY be used if you have not been using specialised functions .add_native_script_input
and .add_plutus_script_input
- these functions register scripts automatically.)
Function .get_native_input_scripts
and .get_plutus_input_scripts
can be used to query the already registered data from the builder.
Script data hash
NOTE: whenever a transaction with plutus script inputs is created, it MUST contain the correct "script data hash" value present or it will not be accepted by nodes. This new field can be operated with new functions:
.set_script_data_hash(ScriptDataHash)
- in case you already have this value calculated yourself.remove_script_data_hash()
- for any case when you need to wipe it from the builder for some reason.calc_script_data_hash(Costmdls)
- this function allows to calculate the hash automatically from the witnesses present in the builder at this moment (so it must be called after adding all inputs and all scripts)
The function .calc_script_data_hash
takes a single parameter with the Plutus language cost models, which you can create yourself from the protocol parameters, or you can use the predefined constant value for the language version PlutusV1
, like this:
txBuilder.calc_script_data_hash(
CardanoWasm.TxBuilderConstants.plutus_default_cost_models(),
);
The new module TxBuilderConstants
contains this single function with the valid (for now) cost model and later might be updated with newer appearing cost models.
Building with scripts validation
The function .build_tx
is now updated to perform two new validations:
- In case there are any missing witness scripts for registered inputs - the function will raise an error
- In case there are any plutus script inputs, but no value for the script data hash - the function will raise another error
This can be avoided by using new function .build_tx_unsafe
, just in case it's needed for some reason.
Fixes
10.0.4 "Script Inputs"
Release PR: #376
Main change:
- The issue that has been causing
hash_script_data
function to produce incorrect hashes for transactions with script inputs is resolved
10.0.3 "Script Signers"
10.0.2 "Total Input"
10.0.1 "Confusing Seed"
Release PR: #361
Changes:
- Versions of the
cryptoxide
anded25519-bip32
libraries are updated in dependencies - Small internal improvements removing code warnings
10.0.0 "Coins per UTXO Word"
Release PR: #358
Milestone: https://github.com/Emurgo/cardano-serialization-lib/milestone/5?closed=1
Breaking Changes
1. Old protocol param minimum_utxo_val
is replaced with coins_per_utxo_word
(#219 #248)
The TransactionBuilder and the min_ada_required
function now require new value introduced in Alonzo: coins per utxo word, see spec from IOHK: https://github.com/input-output-hk/cardano-ledger/blob/master/doc/explanations/min-utxo-alonzo.rst
The mainnet value for this at the moment is 34_482
(lovelaces).
The min_ada_required
function API changed from two required arguments to three: the Value
to be estimated, the boolean flag has_data_hash
(// whether the output includes a plutus data hash
), and the coins_per_utxo_word
as BigNum
.
2. TransactionBuilder construction API changed (#261 #269 #270)
The list of arguments is replaced with a new config struct and the config-builder, see example of the new usage in Rust here: https://github.com/Emurgo/cardano-serialization-lib/blob/master/rust/src/tx_builder.rs#L1144-L1153
In JS it's something like:
RustModule.TransactionBuilder.new(
RustModule.TransactionBuilderConfigBuilder.new()
.fee_algo(linearFee)
.pool_deposit(poolDeposit)
.key_deposit(keyDeposit)
.coins_per_utxo_word(coinsPerUtxoWord)
.max_value_size(maxValueBytes)
.max_tx_size(maxTxBytes)
.build()
);
3. Field replacement in ConstrPlutusData (#250)
The ConstrPlutusData
field tag: Int
is replaced to be alternative: BigNum
4. NativeScript hash return type fixed (#234)
The function ScriptHash.hash
return type changed from incorrect Ed25519KeyHash
to correct ScriptHash
. They are both defined as 28-byte hash types, so functionally there's no fifference but type-checking might fail in strict systems if the incorrect type were used on the client side.
New API features
1. Minting in TransactionBuilder (#231 #273)
The Mint
is now can be set to the tx-builder using new .set_mint
function, but this requires additional manual handling of witness scripts for minting using the new .set_mint_scripts
function. If the fee estimation is attempted without having all matching witness scripts for each used policy-id in the mint - an error will be raised as the correct estimation is not possible. You can still use Mint without providing witness scripts and use automatic change calculation if you set the fee value manually.
Instead, new helper functions can be used: .set_mint_asset
, .add_mint_asset
, .add_mint_asset_and_output
, .add_mint_asset_and_output_min_required_coin
. These function take the minting script itself instead of just the policy-id and they both produce the correct mint entry with the policy-id AND include the minting script into the list of witnesses so that the correct fee estimation is possible. The *_and_output
functions additionally produce a new output specifically for this new minted asset and either include the specified ADA value or automatically calculate and include the minimum required ADA value.
NOTE: added mint is correctly considered as part of the total input so if you don't send it to any explicit output and calculate the change - it will be added to the change output.
2. Metadata in TransactionBuilder (#231)
Few new helper functions for easier metadata handling: .set_metadata
, .add_metadatum
, .add_json_metadatum
, .add_json_metadatum_with_schema
. The set
function overwrites the existing value. All add_*
functions are null-secure, meaning that in case the auxiliary data or the metadata does not exist yet - it will be safely created and then the new entry will be added to it.
3. Building full Tx in TransactionBuilder (#231)
New function .build_tx()
is added which produces an instance of the full Transaction
, compared to the existing .build()
which returns only the TransactionBody
. The important difference is that the full returned Transaction
contains the witness_set
which will already include all the native scripts if minting were added, plus it contains the auxiliary_data
in case the metadata were added, and the validity flag for better compatibility with Alonzo.
If NO minting and no metadata were used - there's not much difference which variant to use. But if minting and/or metadata were added - then it is much more recommended to use .build_tx()
and then only add vkey witnesses into the existing witness_set
after signing the transaction.
4. Coin-selection in TransactionBuilder (#232 #253 #254 #264)
New function .add_inputs_from
is now available which takes an array of available utxo and allows to select the selection strategy: largest-first or random-improve (see CIP2), the function will try to select enough utxo to add them as inputs to cover the required outputs and the fees, which is why it is better to call this function after all target outputs, the mint, and the metadata are added, and before calling .add_change_if_needed
.
5. Building outputs (#231 #304 #359)
New structure TransactionOutputBuilder
is available now to simplify the output creation. It splits the process into two main parts: specifying the address and optional data-hash, and specifying the value in various optional ways.
The flow of using the builder is like:
TransactionOutputBuilder.new()
- creates the initial output-builder and provides these functions:.with_address(Address)
- returns new instance with the set address.with_data_hash(DataHash)
- returns new instance with the set hash.next()
- returns the next step output-value-builder, will fail in case the address is not specified, next builder provides these functions:.with_value(Value)
- returns new instance with the exact specified Value.with_coin(Coin)
- returns new instance with the value having only the specified Coin.with_coin_and_asset(Coin, MultiAsset)
- returns new instance with the value having both specified Coin and MultiAsset.with_asset_and_min_required_coin(MultiAsset, Coin)
- returns new instance with the value having the specified MultiAsset and with the coin value calculated automatically as the minimum required amount to cover the assets. (NOTE: the second argument of typeCoin
is the protocol parametercoins-per-utxo-word
and is required for the min-required-ada calculation.).build()
- returns the final constructedTransactionOutput
instance, will fail in case the amount were not specified in any way.
Example of using this from JS would be something like:
txBuilder.add_output(
TransactionOutputBuilder.new()
.with_address(address)
.next()
.with_asset_and_min_required_coin(multiAsset, config.coins_per_utxo_word)
.build()
);
6. PrivateKey from bech32 (#244 #245)
New construction option PrivateKey::from_bech32
is now available
7. Cardano-wallet style multisig (#221)
New function are now available to create multisig scripts as supported by cardano-wallet, independent to CIP29.
8. Deprecated Int.as_i32
(#258)
Function Int.as_i32()
is deprecated because it silently ignores potential overflow errors and does not indicate it with the name that well. New functions added: .as_i32_or_nothing()
which does the same thing and .as_i32_or_fail()
which potentially returns an error.
Additionally new function Int.to_str
is added, which produces normal decimal string rendering of the underlying i128. Without that function before clients were forced to either use as_i32
or use the awkward BigNum conversion API which requires to do a positive/negative check first.
9. Deprecated TransactionBody.multiassets
(#330)
Function TransactionBody.multiassets()
is a weirdly named getter for the Mint
field in a transaction. This function is deprecated, new properly named function TransactionBody.mint()
is now available and must be used.
Internal improvements
- More secure change with assets with breaking same-policy bundles into multiple outputs if needed (#236 #290)
- Plutus data serialisation fixes (#228)
- Plutus hash script data fixes (#217 #347)
- Asset size calculation fixed to reduce the min-required-ada for utxo a bit (#211)
- Protocol parameters
collateral_percentage
andmax_collateral_inputs
are supported (#308) - Plutus datums now preserve the deserialized bytes and will produce exactly same output if serialized again after being parsed (#317)