baking-bad / pytezos

🐍 Python SDK for Tezos | Michelson VM in Python
https://pytezos.org
MIT License
112 stars 38 forks source link

How to bytepack nested pairs #312

Closed tbinetruy closed 2 years ago

tbinetruy commented 2 years ago

Currently, it seems like pytezos.michelson.micheline.PairType.pack does not byte-pack like a tezos node would for nested pairs.

Example:

from pytezos.michelson.types import MichelsonType
from pytezos.michelson.parse import michelson_to_micheline

message_format = '(pair nat (pair nat (pair nat nat)))'
ty = MichelsonType.match(michelson_to_micheline(message_format))
micheline = michelson_to_micheline('(Pair 1 (Pair 2 (Pair 3 4)))')
message = ty.from_micheline_value(micheline).pack()
message.hex()  # 0x0502000000080001000200030004

Using the tezos-client however, we get a different value:

tezos-client hash data '(Pair 1 (Pair 2 (Pair 3 4)))' of type '(pair nat (pair nat (pair nat nat)))'

# Raw packed data: 0x050707000107070002070700030004

And indeed, the tezos-client cli byte-unpacks the pytezos result as a sequence:

tezos-client unpack michelson data "0x0502000000080001000200030004"
# { 1 ; 2 ; 3 ; 4 }

Whereas it does byte-unpack its result as the expected nested pair:

tezos-client unpack michelson data "0x050707000107070002070700030004"
Pair 1 (Pair 2 (Pair 3 4))

Unfortunately this proves to be problematic when wanting to verify on-chain data that was signed on a Pytezos byte-pack output.

Is there anyway to get the output that tezos-client gives when byte-packing nested pairs using Pytezos? If not, how can I help contributing with a fix? The codebase for the byte-packing looks quite tough :)

Thanks!

P.S. As a side note, byte packing a pair does result in the same output between Pytezos and the Tezos CLI:

message_format = '(pair nat nat)'
ty = MichelsonType.match(michelson_to_micheline(message_format))
micheline = michelson_to_micheline('(Pair 3 4)')
message = ty.from_micheline_value(micheline).pack()
message.hex()  # 0x05070700030004

And:

tezos-client hash data '(Pair 3 4)' of type '(pair nat nat)'
# Raw packed data: 0x05070700030004
m-kus commented 2 years ago

Hey!

You need to pass additional flag:

.pack(legacy=True)

This is from the times before combs, tezos-client does packing with backward compatibility so that things like e.g. big map key hashes remain the same.

tbinetruy commented 2 years ago

Ah niiice, thank you so much :)