# Module `0x1::capability` A module which defines the basic concept of [*capabilities*](https://en.wikipedia.org/wiki/Capability-based_security) for managing access control. EXPERIMENTAL ## Overview A capability is a unforgeable token which testifies that a signer has authorized a certain operation. The token is valid during the transaction where it is obtained. Since the type capability::Cap has no ability to be stored in global memory, capabilities cannot leak out of a transaction. For every function called within a transaction which has a capability as a parameter, it is guaranteed that the capability has been obtained via a proper signer-based authorization step previously in the transaction's execution. ### Usage Initializing and acquiring capabilities is usually encapsulated in a module with a type tag which can only be constructed by this module. ``` module Pkg::Feature { use std::capability::Cap; /// A type tag used in Cap. Only this module can create an instance, /// and there is no public function other than Self::acquire which returns a value of this type. /// This way, this module has full control how Cap is given out. struct Feature has drop {} /// Initializes this module. public fun initialize(s: &signer) { // Create capability. This happens once at module initialization time. // One needs to provide a witness for being the owner of Feature // in the 2nd parameter. <> capability::create(s, &Feature{}); } /// Acquires the capability to work with this feature. public fun acquire(s: &signer): Cap { <> capability::acquire(s, &Feature{}); } /// Does something related to the feature. The caller must pass a Cap. public fun do_something(_cap: Cap) { ... } } ``` ### Delegation Capabilities come with the optional feature of *delegation*. Via Self::delegate, an owner of a capability can designate another signer to be also capable of acquiring the capability. Like the original creator, the delegate needs to present his signer to obtain the capability in his transactions. Delegation can be revoked via Self::revoke, removing this access right from the delegate. While the basic authorization mechanism for delegates is the same as with core capabilities, the target of delegation might be subject of restrictions which need to be specified and verified. This can be done via global invariants in the specification language. For example, in order to prevent delegation all together for a capability, one can use the following invariant: ``` invariant forall a: address where capability::spec_has_cap(a): len(capability::spec_delegates(a)) == 0; ``` Similarly, the following invariant would enforce that delegates, if existent, must satisfy a certain predicate: ``` invariant forall a: address where capability::spec_has_cap(a): forall d in capability::spec_delegates(a): is_valid_delegate_for_feature(d); ``` - [Overview](#@Overview_0) - [Usage](#@Usage_1) - [Delegation](#@Delegation_2) - [Struct `Cap`](#0x1_capability_Cap) - [Struct `LinearCap`](#0x1_capability_LinearCap) - [Resource `CapState`](#0x1_capability_CapState) - [Resource `CapDelegateState`](#0x1_capability_CapDelegateState) - [Constants](#@Constants_3) - [Function `create`](#0x1_capability_create) - [Function `acquire`](#0x1_capability_acquire) - [Function `acquire_linear`](#0x1_capability_acquire_linear) - [Function `validate_acquire`](#0x1_capability_validate_acquire) - [Function `root_addr`](#0x1_capability_root_addr) - [Function `linear_root_addr`](#0x1_capability_linear_root_addr) - [Function `delegate`](#0x1_capability_delegate) - [Function `revoke`](#0x1_capability_revoke) - [Function `remove_element`](#0x1_capability_remove_element) - [Function `add_element`](#0x1_capability_add_element) - [Module Specification](#@Module_Specification_4)
use 0x1::error;
use 0x1::signer;
use 0x1::vector;
## Struct `Cap` The token representing an acquired capability. Cannot be stored in memory, but copied and dropped freely.
struct Cap<Feature> has copy, drop
Fields
root: address
## Struct `LinearCap` A linear version of a capability token. This can be used if an acquired capability should be enforced to be used only once for an authorization.
struct LinearCap<Feature> has drop
Fields
root: address
## Resource `CapState` An internal data structure for representing a configured capability.
struct CapState<Feature> has key
Fields
delegates: vector<address>
## Resource `CapDelegateState` An internal data structure for representing a configured delegated capability.
struct CapDelegateState<Feature> has key
Fields
root: address
## Constants
const ECAP: u64 = 0;
const EDELEGATE: u64 = 1;
## Function `create` Creates a new capability class, owned by the passed signer. A caller must pass a witness that they own the Feature type parameter.
public fun create<Feature>(owner: &signer, _feature_witness: &Feature)
Implementation
public fun create<Feature>(owner: &signer, _feature_witness: &Feature) {
    let addr = signer::address_of(owner);
    assert!(!exists<CapState<Feature>>(addr), error::already_exists(ECAP));
    move_to<CapState<Feature>>(owner, CapState{ delegates: vector::empty() });
}
## Function `acquire` Acquires a capability token. Only the owner of the capability class, or an authorized delegate, can succeed with this operation. A caller must pass a witness that they own the Feature type parameter.
public fun acquire<Feature>(requester: &signer, _feature_witness: &Feature): capability::Cap<Feature>
Implementation
public fun acquire<Feature>(requester: &signer, _feature_witness: &Feature): Cap<Feature>
acquires CapState, CapDelegateState {
    Cap<Feature>{root: validate_acquire<Feature>(requester)}
}
## Function `acquire_linear` Acquires a linear capability token. It is up to the module which owns Feature to decide whether to expose a linear or non-linear capability.
public fun acquire_linear<Feature>(requester: &signer, _feature_witness: &Feature): capability::LinearCap<Feature>
Implementation
public fun acquire_linear<Feature>(requester: &signer, _feature_witness: &Feature): LinearCap<Feature>
acquires CapState, CapDelegateState {
    LinearCap<Feature>{root: validate_acquire<Feature>(requester)}
}
## Function `validate_acquire` Helper to validate an acquire. Returns the root address of the capability.
fun validate_acquire<Feature>(requester: &signer): address
Implementation
fun validate_acquire<Feature>(requester: &signer): address
acquires CapState, CapDelegateState {
    let addr = signer::address_of(requester);
    if (exists<CapDelegateState<Feature>>(addr)) {
        let root_addr = borrow_global<CapDelegateState<Feature>>(addr).root;
        // double check that requester is actually registered as a delegate
        assert!(exists<CapState<Feature>>(root_addr), error::invalid_state(EDELEGATE));
        assert!(vector::contains(&borrow_global<CapState<Feature>>(root_addr).delegates, &addr),
               error::invalid_state(EDELEGATE));
        root_addr
    } else {
        assert!(exists<CapState<Feature>>(addr), error::not_found(ECAP));
        addr
    }
}
## Function `root_addr` Returns the root address associated with the given capability token. Only the owner of the feature can do this.
public fun root_addr<Feature>(cap: capability::Cap<Feature>, _feature_witness: &Feature): address
Implementation
public fun root_addr<Feature>(cap: Cap<Feature>, _feature_witness: &Feature): address {
    cap.root
}
## Function `linear_root_addr` Returns the root address associated with the given linear capability token.
public fun linear_root_addr<Feature>(cap: capability::LinearCap<Feature>, _feature_witness: &Feature): address
Implementation
public fun linear_root_addr<Feature>(cap: LinearCap<Feature>, _feature_witness: &Feature): address {
    cap.root
}
## Function `delegate` Registers a delegation relation. If the relation already exists, this function does nothing.
public fun delegate<Feature>(cap: capability::Cap<Feature>, _feature_witness: &Feature, to: &signer)
Implementation
public fun delegate<Feature>(cap: Cap<Feature>, _feature_witness: &Feature, to: &signer)
acquires CapState {
    let addr = signer::address_of(to);
    if (exists<CapDelegateState<Feature>>(addr)) return;
    move_to(to, CapDelegateState<Feature>{root: cap.root});
    add_element(&mut borrow_global_mut<CapState<Feature>>(cap.root).delegates, addr);
}
## Function `revoke` Revokes a delegation relation. If no relation exists, this function does nothing.
public fun revoke<Feature>(cap: capability::Cap<Feature>, _feature_witness: &Feature, from: address)
Implementation
public fun revoke<Feature>(cap: Cap<Feature>, _feature_witness: &Feature, from: address)
acquires CapState, CapDelegateState
{
    if (!exists<CapDelegateState<Feature>>(from)) return;
    let CapDelegateState{root: _root} = move_from<CapDelegateState<Feature>>(from);
    remove_element(&mut borrow_global_mut<CapState<Feature>>(cap.root).delegates, &from);
}
## Function `remove_element` Helper to remove an element from a vector.
fun remove_element<E: drop>(v: &mut vector<E>, x: &E)
Implementation
fun remove_element<E: drop>(v: &mut vector<E>, x: &E) {
    let (found, index) = vector::index_of(v, x);
    if (found) {
        vector::remove(v, index);
    }
}
## Function `add_element` Helper to add an element to a vector.
fun add_element<E: drop>(v: &mut vector<E>, x: E)
Implementation
fun add_element<E: drop>(v: &mut vector<E>, x: E) {
    if (!vector::contains(v, &x)) {
        vector::push_back(v, x)
    }
}
## Module Specification Helper specification function to check whether a capability exists at address.
fun spec_has_cap<Feature>(addr: address): bool {
   exists<CapState<Feature>>(addr)
}
Helper specification function to obtain the delegates of a capability.
fun spec_delegates<Feature>(addr: address): vector<address> {
   global<CapState<Feature>>(addr).delegates
}