Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Selector Docs #172

Merged
merged 6 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/basics/metadata.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Metadata
hide_title: true
slug: /metadata
slug: /basics/metadata
---

<img src="/img/title/metadata.svg" className="titlePic" />
Expand Down
88 changes: 88 additions & 0 deletions docs/basics/selectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: Selectors
hide_title: true
slug: /basics/selectors
---

# Selectors

Selectors in ink! are a language agnostic way of identifying constructors and messages.
They are four-byte hexadecimal strings which look something like: `0x633aa551`.

You can find the selector of an ink! constructor or message in your
[contract metadata](/basics/metadata) by looking for the `selector` field of the dispatchable
you're interested in.

Here is an example of how you can grab the message name and selector from your contract
metadata using [`jq`](https://stedolan.github.io/jq/).

```
cat target/ink/flipper.json | jq '.spec.messages[0] | "\(.label): \(.selector)"'
"flip: 0x633aa551"
```

## Selector Calculation

If you do not have access to a contract's metadata, you can also calculate it yourself.

The algorithm ink! uses is fairly straightforward:
1. Get the _just_ name of the constructor or message
2. Compute the `BLAKE2` hash of the name
3. Take the first four bytes of the hash as the selector

Let's walk through a short example of what this looks like in practice. Consider the
following message:

```rust
#[ink(message)]
fn frobinate(&mut self, fro: bool, bi: u32, nate: AccountId) -> bool {
unimplemented!()
}
```

To calculate the selector we:
1. Grab the name of the message, `frobinate`
2. Compute `BLAKE2("frobinate") = 0x8e39d7f22ef4f9f1404fe5200768179a8b4f2b67799082d7b39f6a8ca82da8f1`
3. Grab the first four bytes, `0x8e39d7f2`

## Selector Calculation: ink! Traits

These rules change a bit if you define any messages using the `[ink::trait_defintion]`
[macro](/basics/trait-definitions). For our first step, instead of taking _just_ the
message name, we now also add the _trait name_ to the selector calculation.

```
cat target/ink/trait-flipper.json | jq '.spec.messages[0] | "\(.label): \(.selector)"'
"Flip::flip: 0xaa97cade"
```

Let's see what this would look like in practice. Consider the following trait:

```rust
#[ink::trait_definition]
pub trait Frobinate {
fn frobinate(&mut self, fro: bool, bi: u32, nate: AccountId) -> bool;
}

-- snip --

impl Frobinate for Contract {
#[ink(message)]
fn frobinate(&mut self, fro: bool, bi: u32, nate: AccountId) -> bool {
unimplemented!()
}
}
```

To calculate the selector we:
1. Grab the name of the trait **and** the name of the message, `Forbinate::frobinate`
2. Compute `BLAKE2("Forbinate::frobinate") = 0x153eee2e7d585abbfed235e2c10c11dc4f3ab1ce0c2ca033fa065fd1be87d83f`
3. Grab the first four bytes, `0x153eee2e`

:::tip

Don't worry if you're not able to calculate the `BLAKE2` hash of a string by hand. You
can use [Shawn's Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/)
to do it for you!

:::
1 change: 1 addition & 0 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = {
"basics/reading-values",
"basics/mutating-values",
"basics/events",
"basics/selectors",
"basics/trait-definitions",
"basics/cross-contract-calling",
"basics/upgradeability",
Expand Down