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

152 lines
4.2 KiB
Markdown
Raw Normal View History

---
id: tezos-specific
title: Tezos Domain-Specific Operations
---
2020-02-05 19:28:40 +04:00
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.
2020-02-05 19:28:40 +04:00
## Pack and unpack
2020-02-05 19:28:40 +04:00
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.
2020-02-05 19:28:40 +04:00
> ⚠️ `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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
2020-02-05 19:28:40 +04:00
```pascaligo group=a
function id_string (const p : string) : option (string) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed): option (string))
```
<!--CameLIGO-->
2020-02-05 19:28:40 +04:00
```cameligo group=a
let id_string (p : string) : string option =
let packed: bytes = Bytes.pack p in
2020-02-05 19:28:40 +04:00
(Bytes.unpack packed : string option)
```
<!--ReasonLIGO-->
2020-02-05 19:28:40 +04:00
```reasonligo group=a
let id_string = (p : string) : option (string) => {
let packed : bytes = Bytes.pack (p);
(Bytes.unpack(packed) : option (string));
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Hashing Keys
2020-02-05 19:28:40 +04:00
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 an
predefined function returning a value of type `key_hash`.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
2020-02-05 19:28:40 +04:00
```pascaligo group=b
function check_hash_key (const kh1 : key_hash; const k2 : key) : bool * key_hash is block {
2020-02-05 19:28:40 +04:00
var ret : bool := False;
var kh2 : key_hash := crypto_hash_key (k2);
if kh1 = kh2 then ret := True else skip
} with (ret, kh2)
```
<!--CameLIGO-->
2020-02-05 19:28:40 +04:00
```cameligo group=b
let check_hash_key (kh1, k2 : key_hash * key) : bool * key_hash =
let kh2 : key_hash = Crypto.hash_key k2 in
2020-02-05 19:28:40 +04:00
if kh1 = kh2 then true, kh2 else false, kh2
```
<!--ReasonLIGO-->
2020-02-05 19:28:40 +04:00
```reasonligo group=b
let check_hash_key = ((kh1, k2) : (key_hash, key)) : (bool, key_hash) => {
let kh2 : key_hash = Crypto.hash_key(k2);
2020-02-05 19:28:40 +04:00
if (kh1 == kh2) { (true, kh2); } else { (false, kh2); }
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Checking Signatures
2020-02-05 19:28:40 +04:00
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.
2020-02-05 19:28:40 +04:00
> ⚠️ 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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
2020-02-05 19:28:40 +04:00
```pascaligo group=c
function check_signature
2020-02-05 19:28:40 +04:00
(const pk : key;
const signed : signature;
const msg : bytes) : bool
is crypto_check (pk, signed, msg)
```
<!--CameLIGO-->
2020-02-05 19:28:40 +04:00
```cameligo group=c
let check_signature (pk, signed, msg : key * signature * bytes) : bool =
Crypto.check pk signed msg
```
<!--ReasonLIGO-->
2020-02-05 19:28:40 +04:00
```reasonligo group=c
let check_signature =
((pk, signed, msg) : (key, signature, bytes)) : bool => {
Crypto.check (pk, signed, msg);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
2020-02-05 19:28:40 +04:00
## Getting the contract's own address
2020-02-05 19:28:40 +04:00
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 (a.k.a top-level). Using it in
> an auxiliaru function will cause an error.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
2020-02-05 19:28:40 +04:00
```pascaligo group=d
const current_addr : address = self_address
```
<!--CameLIGO-->
2020-02-05 19:28:40 +04:00
```cameligo group=d
let current_addr : address = Current.self_address
```
<!--ReasonLIGO-->
2020-02-05 19:28:40 +04:00
```reasonligo group=d
let current_addr : address = Current.self_address;
```
<!--END_DOCUSAURUS_CODE_TABS-->