Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@

### Changed

- `Value` has been renamed to `Assets`, to leave room to the new builtin-`Value`.
- <strong>⚠️ BREAKING-CHANGE ⚠️</strong><br/><hr/> `Value` has been renamed to `Assets`, to leave room to the new builtin-`Value`.

- <strong>⚠️ BREAKING-CHANGE ⚠️</strong><br/><hr/>[`cardano/transaction/script_purpose.{compare}`](https://aiken-lang.github.io/stdlib/cardano/transaction/script_purpose.html#compare) now follows the ledger's ordering of script purposes, which is the ordering of the `redeemers` list in the script context:

- `Spend` < `Mint` < `Publish` < `Withdraw` < `Vote` < `Propose`.

It previously followed the constructor order of `ScriptPurpose` (`Mint` first, `Withdraw` before `Publish`), which does not match the on-chain ordering. See [#125](https://github.com/aiken-lang/stdlib/issues/125).

## v3.1.0 - 2026-04-25

Expand Down
2 changes: 1 addition & 1 deletion lib/cardano/transaction.ak
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub type Transaction {
validity_range: ValidityRange,
extra_signatories: List<VerificationKeyHash>,
/// > [!IMPORTANT]
/// > Redeemers are ordered by ascending [ScriptPurpose](./transaction.html#ScriptPurpose).
/// > Redeemers are ordered by ascending [ScriptPurpose](./transaction.html#ScriptPurpose), following the internal ledger's ordering of script purposes: [`Spend`](./transaction.html#ScriptPurpose) < [`Mint`](./transaction.html#ScriptPurpose) < [`Publish`](./transaction.html#ScriptPurpose) < [`Withdraw`](./transaction.html#ScriptPurpose) < [`Vote`](./transaction.html#ScriptPurpose) < [`Propose`](./transaction.html#ScriptPurpose). Note that this ordering **differs from the constructor order** of [ScriptPurpose](./transaction.html#ScriptPurpose); see [script_purpose.compare](./transaction/script_purpose.html#compare).
redeemers: Pairs<ScriptPurpose, Redeemer>,
datums: Dict<DataHash, Data>,
id: TransactionId,
Expand Down
30 changes: 20 additions & 10 deletions lib/cardano/transaction/script_purpose.ak
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,42 @@ use cardano/transaction.{
}
use cardano/transaction/output_reference

/// Compare two script purposes, using the same ordering as the one used by
/// the ledger when constructing the
/// [redeemers](./transaction.html#Transaction) list:
///
/// [`Spend`](./transaction.html#ScriptPurpose) < [`Mint`](./transaction.html#ScriptPurpose) < [`Publish`](./transaction.html#ScriptPurpose) < [`Withdraw`](./transaction.html#ScriptPurpose) < [`Vote`](./transaction.html#ScriptPurpose) < [`Propose`](./transaction.html#ScriptPurpose)
///
/// Note that this ordering follows the internal ledger types, and thus
/// differs from the constructor order of
/// [ScriptPurpose](./transaction.html#ScriptPurpose): `Spend` comes before
/// `Mint`, and `Publish` comes before `Withdraw`.
pub fn compare(left: ScriptPurpose, right: ScriptPurpose) -> Ordering {
when left is {
Mint(left) ->
Spend(left) ->
when right is {
Mint(right) -> bytearray.compare(left, right)
Spend(right) -> output_reference.compare(left, right)
_ -> Less
}

Spend(left) ->
Mint(left) ->
when right is {
Spend(right) -> output_reference.compare(left, right)
Mint(_) -> Greater
Mint(right) -> bytearray.compare(left, right)
Spend(_) -> Greater
_ -> Less
}

Withdraw(left) ->
Publish { at: left, .. } ->
when right is {
Withdraw(right) -> credential.compare(left, right)
Publish { at: right, .. } -> int.compare(left, right)
Spend(_) | Mint(_) -> Greater
_ -> Less
}

Publish { at: left, .. } ->
Withdraw(left) ->
when right is {
Publish { at: right, .. } -> int.compare(left, right)
Spend(_) | Mint(_) | Withdraw(_) -> Greater
Withdraw(right) -> credential.compare(left, right)
Spend(_) | Mint(_) | Publish { .. } -> Greater
_ -> Less
}

Expand Down
46 changes: 23 additions & 23 deletions lib/cardano/transaction/script_purpose.test.ak
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,57 @@ use cardano/transaction/script_purpose.{compare}
// --------------------------------------------------------------------- compare

test compare_matrix() {
let mint0 = Mint("0")
let mint1 = Mint("1")

let spend0 = Spend(OutputReference("", 0))
let spend1 = Spend(OutputReference("", 1))

let withdraw0 = Withdraw(VerificationKey("0"))
let withdraw1 = Withdraw(VerificationKey("1"))
let mint0 = Mint("0")
let mint1 = Mint("1")

let publish0 = Publish(0, RegisterCredential(Script(""), Never))
let publish1 = Publish(1, RegisterCredential(Script(""), Never))

let withdraw0 = Withdraw(VerificationKey("0"))
let withdraw1 = Withdraw(VerificationKey("1"))

let vote0 = Vote(StakePool("0"))
let vote1 = Vote(StakePool("1"))

let propose0 = Propose(0, ProposalProcedure(0, Script(""), NicePoll))
let propose1 = Propose(1, ProposalProcedure(0, Script(""), NicePoll))

and {
(compare(mint0, mint0) == Equal)?,
(compare(mint0, mint1) == Less)?,
(compare(mint1, mint0) == Greater)?,
(compare(mint0, spend0) == Less)?,
(compare(mint0, withdraw0) == Less)?,
(compare(mint0, publish0) == Less)?,
(compare(mint0, vote0) == Less)?,
(compare(mint0, propose0) == Less)?,
(compare(spend0, spend0) == Equal)?,
(compare(spend0, spend1) == Less)?,
(compare(spend1, spend0) == Greater)?,
(compare(spend0, mint0) == Greater)?,
(compare(spend0, mint0) == Less)?,
(compare(spend0, withdraw0) == Less)?,
(compare(spend0, publish0) == Less)?,
(compare(spend0, vote0) == Less)?,
(compare(spend0, propose0) == Less)?,
(compare(withdraw0, withdraw0) == Equal)?,
(compare(withdraw0, withdraw1) == Less)?,
(compare(withdraw1, withdraw0) == Greater)?,
(compare(withdraw0, mint0) == Greater)?,
(compare(withdraw0, spend0) == Greater)?,
(compare(withdraw0, publish0) == Less)?,
(compare(withdraw0, vote0) == Less)?,
(compare(withdraw0, propose0) == Less)?,
(compare(mint0, mint0) == Equal)?,
(compare(mint0, mint1) == Less)?,
(compare(mint1, mint0) == Greater)?,
(compare(mint0, spend0) == Greater)?,
(compare(mint0, withdraw0) == Less)?,
(compare(mint0, publish0) == Less)?,
(compare(mint0, vote0) == Less)?,
(compare(mint0, propose0) == Less)?,
(compare(publish0, publish0) == Equal)?,
(compare(publish0, publish1) == Less)?,
(compare(publish1, publish0) == Greater)?,
(compare(publish0, mint0) == Greater)?,
(compare(publish0, spend0) == Greater)?,
(compare(publish0, withdraw0) == Greater)?,
(compare(publish0, withdraw0) == Less)?,
(compare(publish0, vote0) == Less)?,
(compare(publish0, propose0) == Less)?,
(compare(withdraw0, withdraw0) == Equal)?,
(compare(withdraw0, withdraw1) == Less)?,
(compare(withdraw1, withdraw0) == Greater)?,
(compare(withdraw0, mint0) == Greater)?,
(compare(withdraw0, spend0) == Greater)?,
(compare(withdraw0, publish0) == Greater)?,
(compare(withdraw0, vote0) == Less)?,
(compare(withdraw0, propose0) == Less)?,
(compare(vote0, vote0) == Equal)?,
(compare(vote0, vote1) == Less)?,
(compare(vote1, vote0) == Greater)?,
Expand Down
Loading