ligo/gitlab-pages/docs/language-basics/tezos-specific.md
2020-01-23 09:20:42 -05:00

4.0 KiB

id title
tezos-specific Tezos Domain-Specific Operations

LIGO is a language for writing Tezos smart contracts. It would be a little odd if it didn't 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. PACK converts Michelson data structures to a binary format, and UNPACK reverses it. This functionality can be accessed from within LIGO.

⚠️ PACK and UNPACK are features of Michelson that are intended to be used by people that really know what they're doing. There are several failure cases (such as UNPACKing a lambda from an untrusted source), most of which are beyond the scope of this document. Don't 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 weren't the case hashes are much smaller than keys, and storage on blockchains comes at a cost premium. You can hash keys with the key_hash type and associated built in function.

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 kh1, k2 = kh1_k2;
  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 isn't very 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 = (param: (key, signature, bytes)) : bool => {
  let pk, signed, msg = param;
  Crypto.check(pk, signed, msg);
};

Getting The 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 entry-point level. Using it in a utility 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;