Skip to content

Cannot deserialize PlutusV2 script attached to transaction #251

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

Closed
nielstron opened this issue Jun 8, 2023 · 4 comments · Fixed by #293
Closed

Cannot deserialize PlutusV2 script attached to transaction #251

nielstron opened this issue Jun 8, 2023 · 4 comments · Fixed by #293
Labels
bug Something isn't working

Comments

@nielstron
Copy link
Contributor

Describe the bug
Trying to deserialize a transaction from cborhex that was generated and hexlified by PyCardano before, I get the following error

Jun 07 23:45:25 ********[12055]: pycardano.exception.DeserializeException: Cannot deserialize object:
Jun 07 23:45:25 ********[12055]: [b'Y,\x1e\x01\x00\x002222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222>
Jun 07 23:45:25 *********[12055]:  in any valid type from (typing.List[pycardano.plutus.PlutusV2Script], <class 'NoneType'>).

To Reproduce
Serialize a Tx with a PlutusV2 script attached, then deserialize again.

Logs
Logs are above

Expected behavior
Transaction.from_cbor(tx.to_cbor()) should work without problems

Environment and software version (please complete the following information):

  • OS: Ubuntu 22
  • PyCardano Version: latest

Additional context
None

@cffls cffls added the bug Something isn't working label Jun 8, 2023
@MartinSchere
Copy link

Happening for me too with PlutusV1 scripts

@cffls
Copy link
Collaborator

cffls commented Oct 24, 2023

Does the issue still persist in the latest main branch?

@theeldermillenial
Copy link
Contributor

theeldermillenial commented Jan 9, 2024

Yes, I can also confirm this is still a problem. It appears as though it's trying to interpret it as a list of bytes rather than just bytes. If you instantiate the Plutus script class with the bytes that throw the error, it instantiates properly.

@theeldermillenial
Copy link
Contributor

theeldermillenial commented Jan 9, 2024

I think I figured it out. For types that are just wrappers around Python raw data types, there is no attempt to instantiate them. I ran into this issue when implementing ByteString. We should maybe add in a more generic attempt to cast bytes to their wrapper class.

I'll take a stab at this today.

def _restore_typed_primitive(
t: typing.Type, v: Primitive
) -> Union[Primitive, CBORSerializable]:
"""Try to restore a value back to its original type based on information given in field.
Args:
f (type): A type
v (:const:`Primitive`): A CBOR primitive.
Returns:
Union[:const:`Primitive`, CBORSerializable]: A CBOR primitive or a CBORSerializable.
"""
if t is Any or (t in PRIMITIVE_TYPES and isinstance(v, t)):
return v
elif isclass(t) and issubclass(t, CBORSerializable):
return t.from_primitive(v)
elif hasattr(t, "__origin__") and (t.__origin__ is list):
t_args = t.__args__
if len(t_args) != 1:
raise DeserializeException(
f"List types need exactly one type argument, but got {t_args}"
)
t = t_args[0]
if not isinstance(v, list):
raise DeserializeException(f"Expected type list but got {type(v)}")
return IndefiniteList([_restore_typed_primitive(t, w) for w in v])
elif isclass(t) and t == ByteString:
if not isinstance(v, bytes):
raise DeserializeException(f"Expected type bytes but got {type(v)}")
return ByteString(v)
elif isclass(t) and issubclass(t, IndefiniteList):
try:
return IndefiniteList(v)
except TypeError:
raise DeserializeException(f"Can not initialize IndefiniteList from {v}")
elif hasattr(t, "__origin__") and (t.__origin__ is dict):
t_args = t.__args__
if len(t_args) != 2:
raise DeserializeException(
f"Dict types need exactly two type arguments, but got {t_args}"
)
key_t = t_args[0]
val_t = t_args[1]
if not isinstance(v, dict):
raise DeserializeException(f"Expected dict type but got {type(v)}")
return {
_restore_typed_primitive(key_t, key): _restore_typed_primitive(val_t, val)
for key, val in v.items()
}
elif hasattr(t, "__origin__") and (
t.__origin__ is Union or t.__origin__ is Optional
):
t_args = t.__args__
for t in t_args:
try:
return _restore_typed_primitive(t, v)
except DeserializeException:
pass
raise DeserializeException(
f"Cannot deserialize object: \n{v}\n in any valid type from {t_args}."
)
raise DeserializeException(f"Cannot deserialize object: \n{v}\n to type {t}.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants