Closed AngelCastilloB closed 2 months ago
dev-preview@us-east-1
would change:dev-preprod@us-east-1@v2
would change:dev-mainnet@us-east-1
would change:Note: this PR is wrong @AngelCastilloB @mkazlauskas @iccicci. The situation is a bit more subtle.
Plutus encodes lists as indefinite lists EXCEPT empty lists. Empty lists are encoded as finite empty lists for a reason beyond human understanding.
Also, you might want to fix the serializer for maps: https://github.com/input-output-hk/cardano-js-sdk/blob/master/packages/core/src/Serialization/PlutusData/PlutusMap.ts#L10-L33.
The actual behavior also subtle (but a different kind of subtle). Maps are serialised as finite maps if they have less than (or exactly) 23 elements. Starting at 24 elements, it switches to indefinite.
Why 24? Because this is where the size starts being encoded on an additional byte (yet still 2 bytes, like indefinite). So the real cutoff should have been at 256 elements if it were really about saving bytes. But hey, I don't make the rules.
(edit: nevermind that last bit, only the cardano-ledger does that, not Plutus).
Note: this PR is wrong @AngelCastilloB @mkazlauskas @iccicci. The situation is a bit more subtle.
Plutus encodes lists as indefinite lists EXCEPT empty lists. Empty lists are encoded as finite empty lists for a reason beyond human understanding.
Also, you might want to fix the serializer for maps: https://github.com/input-output-hk/cardano-js-sdk/blob/master/packages/core/src/Serialization/PlutusData/PlutusMap.ts#L10-L33.
The actual behavior also subtle (but a different kind of subtle). Maps are serialised as finite maps if they have less than (or exactly) 23 elements. Starting at 24 elements, it switches to indefinite.
Why 24? Because this is where the size starts being encoded on an additional byte (yet still 2 bytes, like indefinite). So the real cutoff should have been at 256 elements if it were really about saving bytes. But hey, I don't make the rules.
Hello @KtorZ thanks for the clarification, BTW where is all this specified 😅 ? I cant find any of this in the CDDL files. I will make the changes to the serialization classes for lists and maps.
BTW where is all this specified 😅 ?
I know.. It's Haskell code. But that's the ground truth.
Which now makes me realize: disregard my comment about maps, only the ledger does that. Plutus seems more reasonable here and only use definite maps. Though now it creates two different serialisation behaviors. Nice.
And for the list part, you need to dig as far as the default implementation of encode
for lists, which is actually here:
BTW where is all this specified 😅 ?
I know.. It's Haskell code. But that's the ground truth.
Which now makes me realize: disregard my comment about maps, only the ledger does that. Plutus seems more reasonable here and only use definite maps. Though now it creates two different serialisation behaviors. Nice.
And for the list part, you need to dig as far as the default implementation of
encode
for lists, which is actually here:
I did reference Data.hs when writing our serializers, but I didn't dig deep enough it seems:
defaultEncodeList :: Serialise a => [a] -> Encoding
defaultEncodeList [] = encodeListLen 0
defaultEncodeList xs = encodeListLenIndef
<> Prelude.foldr (\x r -> encode x <> r) encodeBreak xs
Its kind of random to be honest, anyways, I will make the change to the List. Thanks for the heads up!
Its kind of random to be honest
Completely. I suppose it's for saving one byte. Talk about premature optimization heh. It's really beyond me that a base library providing default serializer would not enforce a canonical encoding. And I can't also blame the Plutus team for not necessarily noticing.
Context
PlutusList is not encoding following canonical CBOR (uses indefinite length array rather than the definite length form). see https://github.com/input-output-hk/cardano-js-sdk/issues/1318
Proposed Solution
PlutusList should encode by default using definite length CBOR arrays.