Skip to main content

Why did the default datatype layout change to @layout comb?

Tom Jack·2 min read·

When compiling to Michelson, LIGO must choose a "layout" for record and variant data types. Unfortunately, Michelson only has binary pair/or types, for esoteric theoretical reasons.

This means that for each record or variant type, LIGO must pick one of the many isomorphic binary tree structures which can represent it in Michelson. This choice needs to be consistent (else we will get type errors) and ideally it should be flexible (so that users can interoperate with Michelson types defined in standards or emitted by other compilers.)

Background

In early versions of LIGO, two layouts were supported: tree and comb.

Layout tree was made the default, primarily because this layout supports record field access and update with cost O(log n), where n is the number of fields in the record type. This layout also sorted fields alphabetically by name, which made it compatible with LIGO's structural handling of record and variant types at the time, where order doesn't matter.

The tree layout was also used for tuple types, and originally this could not be changed.

The comb layout was also supported because it was expected that it would show up in standards and in interop with Michelson generated by other compilers (and indeed it did.) At some point, LIGO was modified to preserve the order of comb layout record fields and variant cases, since this is useful for interop. (The order now also matters for these types; two comb-layout record types are equal in LIGO only if their fields are in the same order.)

Originally, the comb layout had worse performance, with cost O(n) for record field access and updates.

Why change the default?

Since then, Michelson has added native O(log n) record field accesses and updates with the comb layout. Additionally, there is an n-ary pair x y z ... notation for comb layout, which makes large comb pair types cheaper and more readable.

Thus, current best practice is for LIGO developers to almost always mark record and tuple types as @layout comb. This generally leads to smaller code size, and so less gas and storage burn.

It would be more convenient if this were the default. Unfortunately, changing the default is a breaking change. But with 1.0, we are taking the chance to finally make this breaking change...

Variant types still do not have any special comb support in Michelson (again, for esoteric theoretical reasons.) However, for consistency and simplicity, we are making comb layout the default always. We believe that in most cases, the difference will not be significant. Users can explicitly mark variants as @layout tree if desired.

What do I do?

See the How to deal with the change of the default datatype layout to @layout comb ? doc for advice on how to deal with this breaking change.