Skip to content

Commit fcda104

Browse files
committed
Allow users to configure the serialization format for redeemers
1 parent 388ab97 commit fcda104

File tree

2 files changed

+42
-33
lines changed

2 files changed

+42
-33
lines changed

pycardano/txbuilder.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class TransactionBuilder:
124124

125125
initial_stake_pool_registration: Optional[bool] = field(default=False)
126126

127+
use_redeemer_map: Optional[bool] = field(default=True)
128+
"""Whether to serialize redeemers as a map or a list. Default is True."""
129+
127130
_inputs: List[UTxO] = field(init=False, default_factory=lambda: [])
128131

129132
_potential_inputs: List[UTxO] = field(init=False, default_factory=lambda: [])
@@ -496,21 +499,27 @@ def _redeemer_list(self) -> List[Redeemer]:
496499
+ [r for _, r in self._withdrawal_script_to_redeemers if r is not None]
497500
)
498501

499-
def redeemers(self) -> RedeemerMap:
500-
redeemers = RedeemerMap()
501-
for r in self._redeemer_list:
502-
if r.tag is None:
503-
raise InvalidArgumentException(
504-
f"Redeemer tag is not set. Redeemer: {r}"
505-
)
506-
if r.ex_units is None:
507-
raise InvalidArgumentException(
508-
f"Execution units are not set. Redeemer: {r}"
509-
)
510-
k = RedeemerKey(r.tag, r.index)
511-
v = RedeemerValue(r.data, r.ex_units)
512-
redeemers[k] = v
513-
return redeemers
502+
def redeemers(self) -> Redeemers:
503+
redeemer_list = self._redeemer_list
504+
505+
# We have to serialize redeemers as a map if there are no redeemers
506+
if self.use_redeemer_map or not redeemer_list:
507+
redeemers = RedeemerMap()
508+
for r in redeemer_list:
509+
if r.tag is None:
510+
raise InvalidArgumentException(
511+
f"Redeemer tag is not set. Redeemer: {r}"
512+
)
513+
if r.ex_units is None:
514+
raise InvalidArgumentException(
515+
f"Execution units are not set. Redeemer: {r}"
516+
)
517+
k = RedeemerKey(r.tag, r.index)
518+
v = RedeemerValue(r.data, r.ex_units)
519+
redeemers[k] = v
520+
return redeemers
521+
else:
522+
return redeemer_list
514523

515524
@property
516525
def script_data_hash(self) -> Optional[ScriptDataHash]:
@@ -971,15 +980,14 @@ def _build_full_fake_tx(self) -> Transaction:
971980
return tx
972981

973982
def build_witness_set(
974-
self, remove_dup_script: bool = False, post_chang: bool = True
983+
self, remove_dup_script: bool = False
975984
) -> TransactionWitnessSet:
976985
"""Build a transaction witness set, excluding verification key witnesses.
977986
This function is especially useful when the transaction involves Plutus scripts.
978987
979988
Args:
980989
remove_dup_script (bool): Whether to remove scripts, that are already attached to inputs,
981990
from the witness set.
982-
post_chang (bool): Whether to use chang serialization for the witness.
983991
984992
Returns:
985993
TransactionWitnessSet: A transaction witness set without verification key witnesses.
@@ -1017,19 +1025,12 @@ def build_witness_set(
10171025
f"Unsupported script type: {type(script)}"
10181026
)
10191027

1020-
redeemers: Optional[Redeemers] = None
1021-
if self._redeemer_list:
1022-
if not post_chang:
1023-
redeemers = self._redeemer_list
1024-
else:
1025-
redeemers = self.redeemers()
1026-
10271028
return TransactionWitnessSet(
10281029
native_scripts=native_scripts if native_scripts else None,
10291030
plutus_v1_script=plutus_v1_scripts if plutus_v1_scripts else None,
10301031
plutus_v2_script=plutus_v2_scripts if plutus_v2_scripts else None,
10311032
plutus_v3_script=plutus_v3_scripts if plutus_v3_scripts else None,
1032-
redeemer=redeemers,
1033+
redeemer=self.redeemers() if self._redeemer_list else None,
10331034
plutus_data=list(self.datums.values()) if self.datums else None,
10341035
)
10351036

test/pycardano/test_txbuilder.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,8 @@ def test_add_script_input(chain_context):
572572
)
573573
tx_builder.add_output(TransactionOutput(receiver, 5000000))
574574
tx_builder.build(change_address=receiver)
575-
witness = tx_builder.build_witness_set(post_chang=False)
575+
tx_builder.use_redeemer_map = False
576+
witness = tx_builder.build_witness_set()
576577
assert [datum] == witness.plutus_data
577578
assert [redeemer1, redeemer2] == witness.redeemer
578579
assert [plutus_script] == witness.plutus_v1_script
@@ -603,7 +604,8 @@ def test_add_script_input_no_script(chain_context):
603604
)
604605
tx_builder.add_output(TransactionOutput(receiver, 5000000))
605606
tx_builder.build(change_address=receiver)
606-
witness = tx_builder.build_witness_set(remove_dup_script=True, post_chang=False)
607+
tx_builder.use_redeemer_map = False
608+
witness = tx_builder.build_witness_set(remove_dup_script=True, )
607609
assert [datum] == witness.plutus_data
608610
assert [redeemer] == witness.redeemer
609611
assert witness.plutus_v1_script is None
@@ -671,7 +673,8 @@ def test_add_script_input_find_script(chain_context):
671673
)
672674
tx_builder.add_output(TransactionOutput(receiver, 5000000))
673675
tx_body = tx_builder.build(change_address=receiver)
674-
witness = tx_builder.build_witness_set(post_chang=False)
676+
tx_builder.use_redeemer_map = False
677+
witness = tx_builder.build_witness_set()
675678
assert [datum] == witness.plutus_data
676679
assert [redeemer] == witness.redeemer
677680
assert witness.plutus_v1_script is None
@@ -710,7 +713,8 @@ def test_add_script_input_with_script_from_specified_utxo(chain_context):
710713
)
711714
tx_builder.add_output(TransactionOutput(receiver, 5000000))
712715
tx_body = tx_builder.build(change_address=receiver)
713-
witness = tx_builder.build_witness_set(post_chang=False)
716+
tx_builder.use_redeemer_map = False
717+
witness = tx_builder.build_witness_set()
714718
assert [datum] == witness.plutus_data
715719
assert [redeemer] == witness.redeemer
716720
assert witness.plutus_v2_script is None
@@ -981,7 +985,8 @@ def test_add_minting_script_from_specified_utxo(chain_context):
981985
tx_builder.add_output(TransactionOutput(receiver, 5000000))
982986
tx_builder.mint = mint
983987
tx_body = tx_builder.build(change_address=receiver)
984-
witness = tx_builder.build_witness_set(post_chang=False)
988+
tx_builder.use_redeemer_map = False
989+
witness = tx_builder.build_witness_set()
985990
assert witness.plutus_data is None
986991
assert [redeemer] == witness.redeemer
987992
assert witness.plutus_v2_script is None
@@ -1110,7 +1115,8 @@ def test_add_minting_script(chain_context):
11101115
)
11111116
tx_builder.add_output(TransactionOutput(receiver, Value(5000000, mint)))
11121117
tx_builder.build(change_address=receiver)
1113-
witness = tx_builder.build_witness_set(post_chang=False)
1118+
tx_builder.use_redeemer_map = False
1119+
witness = tx_builder.build_witness_set()
11141120
assert [plutus_script] == witness.plutus_v1_script
11151121

11161122

@@ -1132,7 +1138,8 @@ def test_add_minting_script_only(chain_context):
11321138
)
11331139
tx_builder.add_output(TransactionOutput(receiver, Value(5000000, mint)))
11341140
tx_builder.build(change_address=receiver)
1135-
witness = tx_builder.build_witness_set(post_chang=False)
1141+
tx_builder.use_redeemer_map = False
1142+
witness = tx_builder.build_witness_set()
11361143
assert [plutus_script] == witness.plutus_v1_script
11371144

11381145

@@ -1237,7 +1244,8 @@ def test_estimate_execution_unit(chain_context):
12371244
)
12381245
tx_builder.add_output(TransactionOutput(receiver, 5000000))
12391246
tx_builder.build(change_address=receiver)
1240-
witness = tx_builder.build_witness_set(post_chang=False)
1247+
tx_builder.use_redeemer_map = False
1248+
witness = tx_builder.build_witness_set()
12411249
assert [datum] == witness.plutus_data
12421250
assert [redeemer1] == witness.redeemer
12431251
assert redeemer1.ex_units is not None

0 commit comments

Comments
 (0)