https://gitlab.com/tezos/tezos
Raw File
Tip revision: 6d4ba2f91a4d1e2a5b3299eae341edd359aaaf47 authored by Nic Volanschi on 30 January 2024, 16:37:33 UTC
REMOVEME: remove flag to skip 8 odoc errors
Tip revision: 6d4ba2f
global_constants.rst
Global Constants
================

The size limit for :doc:`Michelson <michelson>` contracts is quite small, limited to 60
kilobytes as of Granada protocol. Global constants are a feature added
in Hangzhou protocol that enables the re-use of user-defined Micheline chunks in Michelson scripts, allowing
for larger and more complex contracts on the chain. It works in the
following way:

-  Fragments of Michelson code (written in the :doc:`Micheline format <../shell/micheline>`) are
   registered on the chain via a new operation
   ``register_global_constant``. An example expression might be the
   integer ``999`` or the lambda expression ``{ PUSH int 999; ADD }``
-  Included in the receipt of the operation is a hash of the expression
   registered. For example the hash ``999`` is
   ``expruQN5r2umbZVHy6WynYM8f71F8zS4AERz9bugF8UkPBEqrHLuU8``.
-  Constants can be referenced inside a Michelson script with the new
   primitive ``constant``. For example, we could write a lambda
   equivalent to the one above like so:
   ``{ PUSH int (constant "expruQN5r2umbZVHy6WynYM8f71F8zS4AERz9bugF8UkPBEqrHLuU8"); ADD }``

Global Constant Registration
----------------------------

The new ``register_global_constant`` operation includes an object with a
single key ``"value"``, the value of which is the Micheline expression
to be registered.

You can submit this operation conveniently through a new :doc:`octez-client <cli-commands>` command.
For example, the command:

.. code:: sh

    octez-client register global constant "999" from bootstrap1 --burn-cap 0.017

would result in the output:

::

   Node is bootstrapped.
   Estimated gas: 1440 units (will add 100 for safety)
   Estimated storage: 68 bytes added (will add 20 for safety)
   Operation successfully injected in the node.
   Operation hash is 'onsFknW5iWa6eiTYqAghY4peQZ7JYQUJg5fR8MwAQkMKjXfNqGf'
   NOT waiting for the operation to be included.
   Use command
     octez-client wait for onsFknW5iWa6eiTYqAghY4peQZ7JYQUJg5fR8MwAQkMKjXfNqGf to be included --confirmations 5 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU
   and/or an external block explorer to make sure that it has been included.
   This sequence of operations was run:
     Manager signed operations:
       From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx
       Fee to the baker: ꜩ0.000385
       Expected counter: 1
       Gas limit: 1540
       Storage limit: 88 bytes
       Balance updates:
         tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ................ -ꜩ0.000385
         fees(the baker who will include this operation,0) ... +ꜩ0.000385
       Register Global:
         Value: 999
         This global constant registration was successfully applied
         Balance updates:
           tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.017
         Consumed gas: 1440
         Storage size: 68 bytes
         Global address: expruQN5r2umbZVHy6WynYM8f71F8zS4AERz9bugF8UkPBEqrHLuU8

As you can see, the address of the constant is returned in the operation
receipt in the field ``Global address``. This address is the Base58-encode Blake2b
hash of the binary serialization of the registered Micheline expression.
This means constants are content-addressable - given a particular Micheline
expression, you can always calculate its on-chain address and check if it’s registered.

A few points about registering global constants:

- Global constants may contain references to other constants; however,
  any referenced constants must already be registered on the chain. As a
  corollary, you cannot have cyclic references.
- Global constants are not type-checked before registration - any
  valid Micheline expression may be registered. That said, attempting
  to originate a contract that uses a constant in an ill-typed way will
  fail.
- The total depth of the expression registered as a constant (after
  expanding all constant references) may not exceed 10,000.
- The total number of nodes in the Micheline expression being
  registered (after expanding all constant references) may not exceed
  the ``max_micheline_node_count`` protocol constant. As of Hangzhou
  this is 50,000.
- The total number of bytes in the Micheline expression being
  registered (after expanding all constant references) may not exceed
  the ``max_micheline_bytes_limit`` protocol constant. As of Hangzhou
  this is 50,000.

Originating a Contract that uses Global Constants
-------------------------------------------------

A global constant can be referenced in Michelson scripts via the
primitive ``constant``, which accepts a single string argument, being
the hash of the expression to be referenced at runtime. This primitive
can be used to replace any Micheline node in the bodies of the
``parameter``, ``storage``, ``code``, or ``view`` fields of a Michelson script. For
example, we replace every instance of the type ``lambda unit unit`` and
value 999 with their respective hashes:

.. code-block:: michelson

     parameter (constant "exprtYirrFwYKm6yKLzJNtYRbq49zedYq16BonRvMzHiwSbUekB9YL");
     storage (big_map int (constant "exprtYirrFwYKm6yKLzJNtYRbq49zedYq16BonRvMzHiwSbUekB9YL")); 
     code {
       PUSH int (constant "expruQN5r2umbZVHy6WynYM8f71F8zS4AERz9bugF8UkPBEqrHLuU8");
       # <rest of code>
     };

The full expansion of this contract would be:

.. code-block:: michelson

     parameter (lambda unit unit);
     storage (big_map int (lambda unit unit)); 
     code {
       PUSH int 999;
       # <rest of code>
     };

During origination, all constants are expanded recursively. The
operation will fail if the resulting contract is ill-typed. Global
constant expansion consumes gas; thus, the operation may also fail due
to gas exhaustion.

Global Constants at Runtime
---------------------------

Contracts that use global constants are semantically equivalent to the
contract with all constants expanded.

Note that using the `UNPACK <https://tezos.gitlab.io/michelson-reference/#instr-UNPACK>`__ 
operation to deserialize a lambda which contains a reference to a global
constant is not supported. Similarly, originating a contract which contains
a reference to a global constant using the
`CREATE_CONTRACT <https://tezos.gitlab.io/michelson-reference/#instr-CREATE_CONTRACT>`__ 
instruction will also fail.
back to top