Skip to content

Releases: Emurgo/cardano-serialization-lib

11.0.5 "Cost per Byte"

24 Aug 19:33
Compare
Choose a tag to compare

Release PR: #504

An update to the min-ada fix introduced in two previous releases

11.0.3 "Legacy Coin"

23 Aug 17:50
Compare
Choose a tag to compare

Release PR: #503

An update to the min-ada fix introduced in the previous release

11.0.1 "Alonzo Compatible"

18 Aug 18:20
Compare
Choose a tag to compare

Release PR: #500

A fix of the min-ada calculation to be compatible with Alonzo for now (until the mainnet forks)

11.0.0 "Vasil"

27 Jul 09:46
Compare
Choose a tag to compare

Vasil (Babbage) Hard Fork

Release PR: #487

How to migrate

In case your application must be used continuously by users before and after the hard-fork switch on mainnet, you must plan the migration process.

NOTE: by far most of the changes in the library are backward compatible: all pre-babbage CBOR formats are parsed same as before and also if you are not using any of the new Babbage specific features - the produced CBOR will be in the pre-babbage compatible format, meaning that in most of the cases you can just upgrade your product to the new library version and do nothing else.

One case that requires some additional effort is in case you are using TxBuilderConstants.plutus_default_cost_models() function. The returned cost-models are only valid pre-babbage and later there will be an update that will change what this function returns. But for now there are two new function: .plutus_alonzo_cost_models() (pre-babbage) and .plutus_vasil_cost_models() (babbage). If you are using these provided hardcoded constants you must organise a check that will use either one or the other function depending on the current epoch and the protocol version (whether the hardfork already happened or not). Alternatively you can just dynamically acquire the current valid cost-models from the node or some other API every time and build the parameter object yourself manually, to use instead of the hardcoded values.

API Changes

⚠️ BREAKING CHANGES! #410 #456 #460

Block header body getters

HeaderBody (block header) structure change in #456 , specifically: the functions .nonce_vrf and .leader_vrf don't exist anymore, the yare replaced with .nonce_vrf_or_nothing and .leader_vrf_or_nothing and their return type has changed to potentially return nothing. These function will return non-null result only for blocks BEFORE the hardfork.

Alternative function .vrf_result_or_nothing is added. This function will return non-null result only for blocks AFTER the hardfork.

Helper check functions .has_nonce_and_leader_vrf and .has_vrf_result are also added which will return true only before and after the hardfork, respectively.

Protocol param update: protocol version

The type ProtocolVersions is removed in #410 . It was an incorrect interpretation of the CDDL specification to have the parameter field potentially contain an array of protocol versions. Now the structures properly represent that there is ever strictly one protocol version and two functions changed in the ProtocolParamUpdate type:

  1. .set_protocol_version(ProtocolVersions) is replaced with .set_protocol_version(ProtocolVersion)
  2. .protocol_version() -> ProtocolVersions is replaced with .protocol_version() -> ProtocolVersion

So the argument type and the return type has changed in these functions. Be careful with this.

Protocol param update setters

Two protocol parameters are removed from Cardano in that hardfork: the "decentralisation constant" and the "extra entropy".

The setters for these parameters are removed from the type, but the type will still serialise these fields into the byte representation, in case they have beed read during deserialisation.

NOTE: the getter functions for these fields are still there and are usable (even tho deprecated) for the purpose of backward compatibility to parse and read pre-babbage blocks.

TransactionOutput inline scripts and datums #450

The TransactionOutput struct can now contains EITHER a data-hash or an instance of plutus-data itself, to the existing function .set_data_hash, two new setters have been added: .set_plutus_data and .set_script_ref. Corresponding getters .plutus_data and .script_ref both return an optional value or nothing, same as the existing .data_hash. Helper functions .has_data_hash, .has_plutus_data, .has_script_ref have been added.

NOTE: the data-hash and the plutus-data are alternative values and can NOT be both present in an output both at the same time. Setting either one of them will remove the previously present either value from the output, thus .has_data_hash and .has_plutus_data can NEVER be both true, but can both be false. The script-ref value is independent and can be either present or not by itself.

For more details on inlined scripts and datums, see CIP32 and CIP33.

New type ScriptRef is introduced to be used with the .set_script_ref function, and can be one of two forms: ScriptRef.new_native_script(NativeScript) or ScriptRef.new_plutus_script(PlutusScript).

PlutusV2 scripts #458

The new hardfork introduces a new version of the Plutus language PlutusV2, and the language version of the used script must be known to construct a correct transaction. The problem is that the library does not parse the Plutus language itself and does not understand the scripts, it only processed the PlutusScript type as a sequence of bytes (a compiled script).

Thus the version of the used script must be specified by the library user, for this the PlutusScript type have been updated with new functions:

  1. PlutusScript.new_v2(bytes) (as an alternative for PlutusScript.new(bytes))
  2. PlutusScript.from_bytes_v2(bytes) (as an alterantive for PlutusScript.from_bytes(bytes))
  3. PlutusScript.new_with_version(bytes, Language)
  4. PlutusScript.from_bytes_with_version(bytes, Language)

Plus there's a new getter function .language_version() -> Language which returns the version of a script instance.

The type Language is updated to have a new constructor function Language.new_plutus_v2() as an alternative to the existing Language.new_plutus_v1().

Therefore an example of using the above-mentioned ScriptRef type with PlutusV2 would look like:

ScriptRef.new_plutus_script(PlutusScript.from_bytes_v2(bytes));

This script-ref will serialise differently than it would have in case it contained a PlutusV1 script.

NOTE: All the existing APIs that worked with PlutusScript type before will now continue to work in exactly the same way, even tho the underlying serialization have changed depending on the used language version in these scripts. For example, an instance of a TransactionWitnessSet still accepts plutus scripts in exactly the same way, but then depending on the language version in these scripts it may serialize them into different underlying fields.

The API is kept as much backward compatible as possible.

TransactionBuilder changes

There's a special helper module called TxBuilderConstants providing the function .plutus_default_cost_models() which can be used along with the TransactionBuilder.calc_script_data_hash(...). There are now two new functions available in that type:

  1. TxBuilderConstants.plutus_alonzo_cost_models() - returns the same old costmodels
  2. TxBuilderConstants.plutus_vasil_cost_models() - returns the new costmodels including the PlutusV2 language and the updated cost of PlutusV1.

NOTE: The function .plutus_default_cost_models() still returns the Alonzo models. The switch of the default getter will depend on the IOHK posting the protocol update, activating the new models. For now you can use the new specialised functions to use the precise models needed for the network.

NOTE: The CostModel type is internally updated to not assert the expected size of the costs array. Before Babbage this type were always asserting a cost-model always has strictly 166 values, but for PlutusV2 the cost-model contains 175 values, so this assertion is removed.

NOTE: The function TransactionBuilder.calc_script_data_hash(...) is updated to assert and retain only the costmodels for the language version used in the present plutus inputs. E.g. in case only a PlutusV1 script is present in the builder - the function will raise an error in case the V1 cost model is missing in the passed map and then will only use that V1 cost model to calculate the hash.

New min-required-ada math #450

The logic of how the minimal required ADA amount for a UTxO is changing in that hardfork and is now calculated based on cost per BYTE instead of a cost per utxo WORD as it is happening now before the hardfork.

This means there's now a new protocol parameter : coins_per_utxo_byte as a replacement for the previously existing coins_per_utxo_word. The good news is that the parameters are compatible (for now) and the cost per byte is equal to cost per word divided by eight (since a word is 8 bytes long).

Because of this, the existing API is deprecated but is still USABLE, the function .min_ada_required(value, bool, BigNum), and it still accepts the OLD parameter coins_per_utxo_word (WORD!), to keep all the existing code functioning, until it can be updated. All the math within the function is updated to provide the best estimate of the min required ADA for legacy format outputs (no inlined scripts or datums).

The new alternative function is added: min_ada_for_output(TransactionOutput, DataCost). This function accepts an entire output in it's final form and an instance of a DataCost object, which can be created by one of only two ways:

  1. DataCost.new_coins_per_word(BigNum) (DEPRECATED)
  2. DataCost.new_coins_per_byte(BigNum)

This is done in order to force the library users to explicitly type out the type of the cost value they are using: per-word (DEPRECATED) or per-byte. Note that the per-word cost type is kept around for now, even tho it is deprecated, because the parameters are compatible for now, and to mak...

Read more

11.0.0-rc.6 "Babbage Release Candidate"

12 Jul 16:30
Compare
Choose a tag to compare

Beta release, see details: #478

11.0.0-beta.1 "Babbage Beta Candidate"

17 Jun 20:41
Compare
Choose a tag to compare

Beta release, see details: #463

11.0.0-alpha.1 "Babbage Alpha Candidate"

16 Jun 11:05
Compare
Choose a tag to compare

Alpha release, see details: #459

10.2.0 ".set_collateral"

08 Jun 14:39
Compare
Choose a tag to compare

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:

  1. .add_input
  2. .add_key_input
  3. .add_script_input
  4. .add_native_script_input
  5. .add_plutus_script_input
  6. .add_bootstrap_input
  7. .count_missing_input_scripts
  8. .add_required_native_input_scripts
  9. .add_required_plutus_input_scripts
  10. .get_native_input_scripts
  11. .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:

  1. .set_inputs(TxInputsBuilder)
  2. .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"

20 May 11:31
Compare
Choose a tag to compare

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:

  1. .add_native_script_input - accepts a NativeScript and the input with its value
  2. .add_plutus_script_input - accepts a PlutusWitness 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:

  1. .add_required_native_input_scripts - takes an instance of NativeScripts
  2. .add_required_plutus_input_scripts - takes an instance of PlutusWitnesses (which is just a collection type, similar to NativeScripts)

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:

  1. .set_script_data_hash(ScriptDataHash) - in case you already have this value calculated yourself
  2. .remove_script_data_hash() - for any case when you need to wipe it from the builder for some reason
  3. .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:

  1. In case there are any missing witness scripts for registered inputs - the function will raise an error
  2. 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

  • Large negative integer deserialisation is "fixed" (a hack had to be added, because of an issue in the used library) #392
  • Error message in tx_builder fixed #409

10.0.4 "Script Inputs"

16 Feb 08:16
Compare
Choose a tag to compare

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