Bytes
Bytes are used for serializing data, for example to compute signature hashes. Conversely, they can be used to deserialise external data, in which case the expected LIGO type needs to be specified.
Literals
Byte literals are sequences of bytes (eight-bit values, also known as
octets), defined using the prefix 0x
followed by hexadecimal
digits, or none if the denoted literal is zero:
Clearly, this means that literal bytes are always comprised of an even number of hexadecimal digits (because one hexadecimal digit requires up to four bits in binary, and eight are needed to make up a byte).
From numbers to bytes and back
Some other numerals can be converted to bytes by means of calling the
predefined function bytes
, which is overloaded. The reverse
conversion is done by the predefined functions int
and nat
. For
instance, here how to create bytes from natural numbers and integers:
Note: See Two's complement.
From strings
A string literal can be converted to bytes in two ways:
- by interpreting the ASCII code of each character (which spans over two hexadecimal digits) as one byte;
- by interpreting directly each character as one hexadecimal digit.
In the former case, the syntax is somewhat odd -- as opposed to simply
calling the function bytes
:
The latter case is implemented as a type cast:
Note that both syntaxes apply respectively only to verbatim string literals and general strings, not general expressions of type
string
. In other words, the contents of the strings must be available at compile-time. (This actually reveals that("666f6f" as bytes)
is not really a cast, as casts are non-operations.)
Concatenating
Two or more bytes can be concatenated.
Sizing
In order to obtain the length of a sequence of bytes, use the
predefined function Bytes.length
like so:
Slicing
Bytes can be extracted using the predefined function Bytes.sub
. The
first parameter is the start index and the second is the number of
bytes of the slice we want. Keep in mind that the first byte in a
sequence has index 0n
.
Bitwise operations
The bitwise operations on sequences of bytes are as follows:
Packing and unpacking
As Michelson provides the instructions PACK
and UNPACK
for data
serialisation, so does LIGO with Bytes.pack
and Bytes.unpack
. The
former serialises Michelson data structures into a binary format, and
the latter reverses that transformation. Unpacking may fail, so the
return type of Byte.unpack
is an option that needs to be annotated.
Note:
PACK
andUNPACK
are Michelson instructions that are intended to be used by people that really know what they are doing. There are several risks and failure cases, such as unpacking a lambda from an untrusted source or casting the result to the wrong type. Be careful.
Cryptography
One common use of bytes, beyond packing and unpacking, is
cryptography. The predefined module Crypto
provides the following
hashing functions, which are efficient because they are natively
supported by the Michelson virtual machine: