ligo/gitlab-pages/docs/language-basics/tezos-specific.md

4.2 KiB

id title
tezos-specific Tezos Domain-Specific Operations

LIGO is a programming language for writing Tezos smart contracts. It would be a little odd if it did not have any Tezos specific functions. This page will tell you about them.

Pack and Unpack

Michelson provides the PACK and UNPACK instructions for data serialization. The instruction PACK converts Michelson data structures into a binary format, and UNPACK reverses that transformation. This functionality can be accessed from within LIGO.

⚠️ PACK and UNPACK 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, and most of which are beyond the scope of this document. Do not use these functions without doing your homework first.

function id_string (const p : string) : option (string) is block {
  const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed): option (string))
let id_string (p : string) : string option =
  let packed: bytes = Bytes.pack p in
  (Bytes.unpack packed : string option)
let id_string = (p : string) : option (string) => {
  let packed : bytes = Bytes.pack (p);
  (Bytes.unpack(packed) : option (string));
};

Hashing Keys

It is often desirable to hash a public key. In Michelson, certain data structures such as maps will not allow the use of the key type. Even if this were not the case, hashes are much smaller than keys, and storage on blockchains comes at a cost premium. You can hash keys with a predefined functions returning a value of type key_hash.

function check_hash_key (const kh1 : key_hash; const k2 : key) : bool * key_hash is
  block {
    var ret : bool := False;
    var kh2 : key_hash := crypto_hash_key (k2);
    if kh1 = kh2 then ret := True else skip
  } with (ret, kh2)
let check_hash_key (kh1, k2 : key_hash * key) : bool * key_hash =
  let kh2 : key_hash = Crypto.hash_key k2 in
  if kh1 = kh2 then true, kh2 else false, kh2
let check_hash_key = ((kh1, k2) : (key_hash, key)) : (bool, key_hash) => {
  let kh2 : key_hash = Crypto.hash_key(k2);
  if (kh1 == kh2) { (true, kh2); } else { (false, kh2); }
};

Checking Signatures

Sometimes a contract will want to check that a message has been signed by a particular key. For example, a point-of-sale system might want a customer to sign a transaction so it can be processed asynchronously. You can do this in LIGO using the key and signature types.

⚠️ There is no way to generate a signed message in LIGO. This is because that would require storing a private key on chain, at which point it is not... private anymore.

function check_signature
    (const pk     : key;
     const signed : signature;
     const msg    : bytes) : bool
  is crypto_check (pk, signed, msg)
let check_signature (pk, signed, msg : key * signature * bytes) : bool =
  Crypto.check pk signed msg
let check_signature =
  ((pk, signed, msg) : (key, signature, bytes)) : bool => {
  Crypto.check (pk, signed, msg);
};

Contract's Own Address

Often you want to get the address of the contract being executed. You can do it with self_address.

⚠️ Due to limitations in Michelson, self_address in a contract is only allowed at the entrypoint level, that is, at the top-level. Using it in an embedded function will cause an error.

const current_addr : address = self_address
let current_addr : address = Current.self_address
let current_addr : address = Current.self_address;