Skip to content

Edit Accounts Keys and Inbox articles #246

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
71 changes: 22 additions & 49 deletions docs/language/accounts/inbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@ title: Inbox
sidebar_position: 6
---

Accounts have an inbox,
which allows making [capabilities](../capabilities.md) available to specific accounts.
The inbox provides a convenient way to "bootstrap" capabilities:
setting up an initial connection between two accounts,
that the accounts can use to transfer data or perform actions.
Accounts have an inbox, which allows making [capabilities] available to specific accounts. The inbox provides a convenient way to _bootstrap_ capabilities, which sets up an initial connection between two accounts that the accounts can use to transfer data or perform actions.

An account exposes its inbox through the `inbox` field,
which has the type `Account.Inbox`.
An account exposes its inbox through the `inbox` field, which has the type `Account.Inbox`.

## `Account.Inbox`

Expand Down Expand Up @@ -50,25 +45,18 @@ entitlement ClaimInboxCapability

## Publishing a capability to the account inbox

An account (the provider) that would like to provide a capability to another account (the recipient)
can do so using the `publish` function:
An account (the provider) that would like to provide a capability to another account (the recipient) can do so using the `publish` function:

```cadence
access(Inbox | PublishInboxCapability)
fun publish(_ value: Capability, name: String, recipient: Address)
```

Calling the `publish` function requires access to an account via a reference which is authorized
with the coarse-grained `Inbox` entitlement (`auth(Inbox) &Account`),
or the fine-grained `PublishInboxCapability` entitlement (`auth(PublishInboxCapability) &Account`).
Calling the `publish` function requires access to an account via a reference, which is authorized with the coarse-grained `Inbox` entitlement (`auth(Inbox) &Account`), or the fine-grained `PublishInboxCapability` entitlement (`auth(PublishInboxCapability) &Account`).

The function publishes the specified capability using the provided string as an identifier, to be later claimed by the recipient.
Note, however, that until the recipient claims the capability, the provider's account stores it,
and the capability contributes towards the provider's account storage usage.
The function publishes the specified capability using the provided string as an identifier, to be later claimed by the recipient. Note, however, that until the recipient claims the capability, the provider's account stores it, and the capability contributes towards the provider's account storage usage.

Calling this function emits an event, `InboxValuePublished`,
that includes the address of both the provider and the recipient, as well as the name and the type of the published capability.
Refer to the [Core Events page](../core-events.md#inbox-value-published) for more details on this event.
Calling this function emits an event, `InboxValuePublished`, that includes the address of both the provider and the recipient, as well as the name and the type of the published capability. Refer to [Inbox Value Published] for more details on this event.

## Claiming a capability from the account inbox

Expand All @@ -79,55 +67,40 @@ access(Inbox | ClaimInboxCapability)
fun claim<T: &Any>(_ name: String, provider: Address): Capability<T>?
```

Calling the `claim` function requires access to an account via a reference which is authorized
with the coarse-grained `Inbox` entitlement (`auth(Inbox) &Account`),
or the fine-grained `ClaimInboxCapability` entitlement (`auth(ClaimInboxCapability) &Account`).
Calling the `claim` function requires access to an account via a reference, which is authorized with the coarse-grained `Inbox` entitlement (`auth(Inbox) &Account`), or the fine-grained `ClaimInboxCapability` entitlement (`auth(ClaimInboxCapability) &Account`).

If the provider's inbox has a capability stored under the provided name,
the calling recipient is the intended recipient,
and it conforms to the provided type argument,
then the function removes the capability from the provider's inbox and returns it.
If the provider's inbox has a capability stored under the provided name, the calling recipient is the intended recipient, and it conforms to the provided type argument, then the function removes the capability from the provider's inbox and returns it.

If the provider's inbox has no capability stored under the provided name,
or if the calling recipient is not the intended recipient,
the function returns `nil`.
If the borrow type of the capability is not a subtype of the provided type argument,
the program aborts.
If the provider's inbox has no capability stored under the provided name, or if the calling recipient is not the intended recipient, the function returns `nil`. If the borrow type of the capability is not a subtype of the provided type argument, the program aborts.

:::tip

It is only possible to claim a capability once.

:::

Calling function `claim` function emits an event, `InboxValueClaimed`,
that includes the address of both the provider and the recipient,
as well as the name of the claimed capability.
Refer to the [Core Events page](../core-events.md#inbox-value-claimed) for more details on this event.
Calling the `claim` function emits an event, `InboxValueClaimed`, that includes the address of both the provider and the recipient, as well as the name of the claimed capability. Refer to [Inbox Value Claimed] for more details on this event.

## Unpublishing a capability from the account inbox

If the provider no longer wishes to publish a capability for some reason,
they can unpublish the capability using the `unpublish` function:
If the provider no longer wishes to publish a capability for some reason, they can unpublish the capability using the `unpublish` function:

```cadence
access(Inbox | UnpublishInboxCapability)
fun unpublish<T: &Any>(_ name: String): Capability<T>?
```

Calling the `unpublish` function requires access to an account via a reference which is authorized
with the coarse-grained `Inbox` entitlement (`auth(Inbox) &Account`),
or the fine-grained `UnpublishInboxCapability` entitlement (`auth(UnpublishInboxCapability) &Account`).
Calling the `unpublish` function requires access to an account via a reference, which is authorized with the coarse-grained `Inbox` entitlement (`auth(Inbox) &Account`), or the fine-grained `UnpublishInboxCapability` entitlement (`auth(UnpublishInboxCapability) &Account`).

If the provider's inbox has a capability stored under the provided name,
and it conforms to the provided type argument,
then the function removes the capability from the inbox and returns it.
If the provider's inbox has a capability stored under the provided name, and it conforms to the provided type argument, then the function removes the capability from the inbox and returns it.

If the provider's inbox has no capability stored under the provided name,
the function returns `nil`.
If the borrow type of the capability is not a subtype of the provided type argument,
the program aborts.
If the provider's inbox has no capability stored under the provided name, the function returns `nil`. If the borrow type of the capability is not a subtype of the provided type argument, the program aborts.

Calling the `unpublish` function emits an event, `InboxValueUnpublished`,
that includes the address of the provider, and the name of the unpublished capability.
Refer to the [Core Events page](../core-events.md#inbox-value-unpublished) for more details on this event.
Calling the `unpublish` function emits an event, `InboxValueUnpublished`, which includes the address of the provider and the name of the unpublished capability. Refer to [Inbox Value Unpublished] for more details on this event.

<!-- Relative links. Will not render on the page -->

[capabilities]: ../capabilities.md
[Inbox Value Published]: ../core-events.md#inbox-value-published
[Inbox Value Claimed]: ../core-events.md#inbox-value-claimed
[Inbox Value Unpublished]: ../core-events.md#inbox-value-unpublished
68 changes: 25 additions & 43 deletions docs/language/accounts/keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@ title: Keys
sidebar_position: 4
---

Accounts have keys associated with them.
When a key is added to an account,
the key can be used to sign a [transaction](../transactions.md),
which in turn gets access the account
and can [perform write operations](./index.mdx#performing-write-operations) on it.
Accounts have keys associated with them. When a key is added to an account, the key can be used to sign a [transaction], which in turn gets access to the account and can [perform write operations] on it.

An account exposes its keys through the `keys` field,
which has the type `Account.Keys`.
An account exposes its keys through the `keys` field, which has the type `Account.Keys`.

## `Account.Keys`

Expand All @@ -24,7 +19,7 @@ struct Keys {

/// Returns the key at the given index, if it exists, or nil otherwise.
///
/// Revoked keys are always returned, but they have `isRevoked` field set to true.
/// Revoked keys are always returned, but they have an `isRevoked` field set to true.
access(all)
view fun get(keyIndex: Int): AccountKey?

Expand Down Expand Up @@ -91,48 +86,37 @@ struct AccountKey {
}
```

A valid account key's `publicKey` field is a `PublicKey` of either the
`ECDSA_P256` or `ECDSA_secp256k1` signature algorithm.
Public keys of other signature algorithms supported by Cadence are
not valid account public keys.
A valid account key's `publicKey` field is a `PublicKey` of either the `ECDSA_P256` or `ECDSA_secp256k1` signature algorithm. Public keys of other signature algorithms supported by Cadence are not valid account public keys.

Refer to the [public keys section](../crypto.mdx#public-keys)
for more details on the creation and validity of public keys.
Refer to the [public keys section] for more details on the creation and validity of public keys.

A valid account key's `hashAlgorithm` field is either `SHA2_256` or `SHA3_256`.
All other hash algorithms supported by Cadence are
not valid for hashing with an account key.
A valid account key's `hashAlgorithm` field is either `SHA2_256` or `SHA3_256`. All other hash algorithms supported by Cadence are not valid for hashing with an account key.

Refer to the [hash algorithms section](../crypto.mdx#hash-algorithms)
for more details on hash algorithms.
Refer to the [hash algorithms section] for more details on hash algorithms.

## Getting an account key

The functions `keys.get` and `keys.forEach` allow retrieving the keys of an account.

The `get` function allows retrieving a key with a specific index.
The function returns the key if it exists, and `nil` otherwise.
The `get` function allows retrieving a key with a specific index. The function returns the key if it exists, and `nil` otherwise:

```cadence
access(all)
view fun get(keyIndex: Int): AccountKey?
```

The `forEach` function allows iterating over all keys of an account.
The `forEach` function allows iterating over all keys of an account:

```cadence
access(all)
fun forEach(_ function: fun(AccountKey): Bool)
```

For each key of the account, the `forEach` function calls the given callback, passing the key to it.
When the callback function returns `true` the iteration continues,
and when it returns `false`, iteration stops.
For each key of the account, the `forEach` function calls the given callback, passing the key to it. When the callback function returns `true`, the iteration continues, and when it returns `false`, the iteration stops.

:::warning

The `keys.get` and `keys.forEach` functions include revoked keys,
which have the `isRevoked` field set to `true`.
The `keys.get` and `keys.forEach` functions include revoked keys, which have the `isRevoked` field set to `true`.

:::

Expand All @@ -155,7 +139,7 @@ fun main() {

## Adding an account key

The function `keys.add` allows a key to access an account.
The function `keys.add` allows a key to access an account:

```cadence
access(Keys | AddKey)
Expand All @@ -166,12 +150,9 @@ fun add(
): AccountKey
```

Calling the `add` function requires access to an account via a reference which is authorized
with the coarse-grained `Keys` entitlement (`auth(Keys) &Account`),
or the fine-grained `AddKey` entitlement (`auth(AddKey) &Account`).
Calling the `add` function requires access to an account via a reference, which is authorized with the coarse-grained `Keys` entitlement (`auth(Keys) &Account`), or the fine-grained `AddKey` entitlement (`auth(AddKey) &Account`).

For example, to add a public key to an existing account,
which signed the transaction:
For example, to add a public key to an existing account that signed the transaction:

```cadence
transaction(publicKey: [UInt8]) {
Expand All @@ -190,10 +171,7 @@ transaction(publicKey: [UInt8]) {
}
```

A more complex transaction, which creates an account,
has the signer of the transaction pay for the account creation,
and authorizes one key to access the account,
could look like:
A more complex transaction, which creates an account, has the signer of the transaction pay for the account creation, and authorizes one key to access the account, could look like:

```cadence
transaction(publicKey: [UInt8]) {
Expand All @@ -216,19 +194,16 @@ transaction(publicKey: [UInt8]) {

## Revoking an account key

The `revoke` function revokes a key from accessing an account.
The function only marks the key at the given index as revoked, but never deletes it.
The `revoke` function revokes a key from accessing an account. The function only marks the key at the given index as revoked, but never deletes it:

```cadence
access(Keys | RevokeKey)
fun revoke(keyIndex: Int): AccountKey?
```

Calling the `revoke` function requires access to an account via a reference which is authorized
with the coarse-grained `Keys` entitlement (`auth(Keys) &Account`),
or the fine-grained `RevokeKey` entitlement (`auth(RevokeKey) &Account`).
Calling the `revoke` function requires access to an account via a reference, which is authorized with the coarse-grained `Keys` entitlement (`auth(Keys) &Account`), or the fine-grained `RevokeKey` entitlement (`auth(RevokeKey) &Account`).

For example, to revoke the third key of the account which signed the transaction:
For example, to revoke the third key of the account that signed the transaction:

```cadence
transaction {
Expand All @@ -238,3 +213,10 @@ transaction {
}
}
```

<!-- Relative links. Will not render on the page -->

[transaction]: ../transactions.md
[perform write operations]: ./index.mdx#performing-write-operations
[public keys section]: ../crypto.mdx#public-keys
[hash algorithms section]: ../crypto.mdx#hash-algorithms