-
-
Notifications
You must be signed in to change notification settings - Fork 79
Add support for NonEmptyOrderedSet in Plutus_data #451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #451 +/- ##
==========================================
- Coverage 89.98% 89.97% -0.02%
==========================================
Files 33 33
Lines 4854 4867 +13
Branches 733 736 +3
==========================================
+ Hits 4368 4379 +11
- Misses 314 315 +1
- Partials 172 173 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This fixes #450 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I have a basic understanding of what you are trying to accomplish. My main concern was that, with this change, all plutus data will be converted to NonEmptyOrderedSet
, regardless of their original format. This might break all transactions generated pre-conway. Since you've fixed the serialization part, I don't think the forced conversion is required in script_data_hash
, but happy to discuss further or help with debugging if you have a concrete example of failure test cases.
pycardano/utils.py
Outdated
if not redeemers: | ||
redeemer_bytes = cbor2.dumps({}, default=default_encoder) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should just check if the redeemer is actually None, and if so, assign an empty redeemer instance to it: redeemers = Redeemers()
, similar to the implementation here, and the encoding will be automatically handled.
redeemer_bytes = cbor2.dumps({}, default=default_encoder) | |
if redeemers is None: | |
redeemers = Redeemers() |
Empty Redeemers()
will be encoded as A0
.
pycardano/utils.py
Outdated
if isinstance(datums, list): | ||
# If datums is a NonEmptyOrderedSet, convert it to a shallow primitive representation | ||
# to ensure correct CBOR encoding | ||
datums = NonEmptyOrderedSet(datums) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it is a good idea to convert it to NonEmptyOrderedSet
. Ideally, script_data_hash
should never change its input, because all items, including redeemers and datums, should match exactly to their representation in the witness set. See this: https://github.com/IntersectMBO/cardano-ledger/blob/1f0c6a4eaa4fb8f937c30a4608a4fafedaca216e/eras/conway/impl/cddl-files/conway.cddl#L449-L451
test/pycardano/test_util.py
Outdated
@@ -156,22 +166,39 @@ def test_script_data_hash(): | |||
redeemers = [Redeemer(unit, ExecutionUnits(1000000, 1000000))] | |||
redeemers[0].tag = RedeemerTag.SPEND | |||
assert ScriptDataHash.from_primitive( | |||
"032d812ee0731af78fe4ec67e4d30d16313c09e6fb675af28f825797e8b5621d" | |||
"2ad155a692b0ddb6752df485de0a6bdb947757f9f998ff34a6f4b06ca0664fbe" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to violate the purpose of unit test. The test was written to ensure a known working datum hash remains working. If it has to change, it means the code changes have broken something. If the purpose is to test the case where datums
is wrapped in NonEmptyOrderedSet
, please create a new test.
test/pycardano/test_util.py
Outdated
def test_script_data_hash_datum_only(): | ||
unit = Unit() | ||
assert ScriptDataHash.from_primitive( | ||
"2f50ea2546f8ce020ca45bfcf2abeb02ff18af2283466f888ae489184b3d2d39" | ||
"264ea21d9904cd72ce5038fa60e0ddd0859383f7fbf60ecec6df22e4c4e34a1f" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, changing hash in unit test isn't a good idea.
Thanks for the quick feedback. I will work on changes and revert. |
…t_data_hash in test_script_data_hash_redeemer_map
if not isinstance(datums, NonEmptyOrderedSet): | ||
# If datums is not a NonEmptyOrderedSet, handle it as a list | ||
datum_bytes = cbor2.dumps(datums, default=default_encoder) | ||
else: | ||
datum_bytes = cbor2.dumps( | ||
datums.to_shallow_primitive(), default=default_encoder | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why this change is needed. The default_encoder
will be able to call to_shallow_primitive
when the datum is not a list. We can keep the original implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was needed the way it is because NonEmptyOrderedSet also inherits from other types that might cause incorrect behavior here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for checking. I think there might be some issue in the way the cbor encodes the OrderedSet
. I will play with it a bit and see if there is a better solution.
pycardano/utils.py
Outdated
cost_models_bytes = cbor2.dumps( | ||
cost_models, | ||
default=default_encoder, | ||
canonical=True, # Ensures definite length encoding and canonical map keys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might break existing unit tests.
test/pycardano/test_util.py
Outdated
def test_script_data_hash_datum_only(): | ||
unit = Unit() | ||
assert ScriptDataHash.from_primitive( | ||
"2f50ea2546f8ce020ca45bfcf2abeb02ff18af2283466f888ae489184b3d2d39" | ||
"244926529564c04ffdea89005076a6b6aac5e4a2f38182cd48bfbc734b3be296" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I don't think we should allow the hash to change in the unit test.
test/pycardano/test_util.py
Outdated
) == script_data_hash(redeemers=[], datums=[unit]) | ||
|
||
|
||
def test_script_data_hash_redeemer_only(): | ||
unit = Unit() | ||
redeemers = [] | ||
assert ScriptDataHash.from_primitive( | ||
"a88fe2947b8d45d1f8b798e52174202579ecf847b8f17038c7398103df2d27b0" | ||
"9eb0251b2e85b082c3706a3e79b4cf2a2e96f936e912a398591e2486c757f8c1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
I was able to fix the other issues, thought I reverted the hashes in the previous one but I maybe didn't check them properly. Now |
This pull request improves handling of indefinite lists, update encoding of Plutus data, and expanded test coverage. Key changes include updates to the
OrderedSet
class to support indefinite lists, modifications to the transaction builder and utilities for more robust Plutus data handling, and update tests to validate these updates.Enhancements to
OrderedSet
and Serialization:OrderedSet
class to inherit fromIndefiniteList
and added support for indefinite list detection and representation. This ensures compatibility with CBOR encoding for both definite and indefinite lists (pycardano/serialization.py
). [1] [2] [3]NonEmptyOrderedSet
to acceptIndefiniteList
as input, improving its flexibility (pycardano/serialization.py
).Improvements in Plutus Data Handling:
TransactionWitnessSet
to supportNonEmptyOrderedSet
forplutus_data
(pycardano/witness.py
). [1] [2]build_witness_set
method to useNonEmptyOrderedSet
for Plutus data (pycardano/txbuilder.py
). [1] [2] [3]Enhancements to Utilities:
script_data_hash
function to handleNonEmptyOrderedSet
for datums and ensure canonical CBOR encoding for cost models (pycardano/utils.py
).Test Coverage Expansion:
script_data_hash
behavior withRedeemerMap
and updated expected hash values to reflect changes in encoding logic (test/pycardano/test_util.py
).test/pycardano/test_txbuilder.py
).