A gym tool Holochain Gym Concepts Developers Core Concepts Toggle darkmode Glossary of Terms Give us Feedback!

Intermediate: Capability Tokens

Capability tokens are the unified security model of holochain. Whenever you want to call a zome function, the conductor will check whether you have capabilities to call it, and return and error if that's not the case.

This includes:

  • Remote calls from other agents in the network
  • Bridged calls from other DNAs
  • Calls from the UI (this is not working yet)

Keep in mind that when trying to do a bridge call from a cell, if it has the same agent pub key as the callee cell, those are the same agent so the call will always be authorized to do so.

By default, all calls from other agent pub keys are not authorized. This means that if I try to do a remote call to another agent without having set up the capability tokens first, it will return an unauthorized error.

Demo

First, we are going to demo how capabilities work at a high level:

  1. Click Run to start the simulation.
  • At every step, you can see what is happening with the nodes on the right panel.
  1. When you are ready, click the "Play" icon on the bottom of the right panel to advance the simulation.

You can rerun it if needed.

Subconsious Checks

When a zome function call is received, holochain's subconscious does these checks:

  • Is the called signed by the agent that sent it? (The signing is done automatically by the sender)
    • If not, return unauthorized error
  • Is the public key of the agent the same one than the one of the cell we are trying to call?
    • If so, skip all other checks
  • Do I have an unrevoked capability grant for this zome function, that contains the secret and the agent that is trying to do the call as an assignee?
    • If not, return unauthorized error

HDK actions

  • generate_cap_secret: creates a new random capability secret
  • create_cap_grant: creates a capability grant with the given access configuration
  • create_cap_claim: creates a capability to store the secret that allows the agent to call that zome function
  • update_cap_grant: updates the given capability grant
  • delete_cap_grant: revokes the given capability grant, so new calls with that secret or agent will fail

Data structures

/// The entry for the ZomeCall capability grant.
/// This data is committed to the callee's source chain as a private entry.
/// The remote calling agent must provide a secret and we source their pubkey from the active
/// network connection. This must match the strictness of the CapAccess.
pub struct CapabilityGrant {
    /// A string by which to later query for saved grants.
    /// This does not need to be unique within a source chain.
    pub tag: String,
    /// Specifies who may claim this capability, and by what means
    pub access: CapAccess,
    /// Set of functions to which this capability grants ZomeCall access
    pub functions: GrantedFunctions,
    // @todo the payloads to curry to the functions
    // pub curry_payloads: CurryPayloads,
}

/// Represents access requirements for capability grants.
enum CapAccess {
    /// No restriction: callable by anyone.
    Unrestricted,
    /// Callable by anyone who can provide the secret.
    Transferable {
        /// The secret.
        secret: CapSecret,
    },
    /// Callable by anyone in the list of assignees who possesses the secret.
    Assigned {
        /// The secret.
        secret: CapSecret,
        /// Agents who can use this grant.
        assignees: HashSet<AgentPubKey>,
    },
}

/// System entry to hold a capability token claim for use as a caller.
/// Stored by a claimant so they can remember what's necessary to exercise
/// this capability by sending the secret to the grantor.
 struct CapabilityClaim {
    /// A string by which to later query for saved claims.
    /// This does not need to be unique within a source chain.
    tag: String,
    /// AgentPubKey of agent who authored the corresponding CapGrant.
    grantor: AgentPubKey,
    /// The secret needed to exercise this capability.
    /// This is the only bit sent over the wire to attempt a remote call.
    /// Note that the grantor may have revoked the corresponding grant since we received the claim
    /// so claims are only ever a 'best effort' basis.
    secret: CapSecret,
}

Exercise

Problem statement

We need to code a small zome that has the following abilities:

  • Give Unrestricted capability access to other agents so agents may receive cap secrets for transferable or assigned tokens
  • Ability to grant transferable cability access to some agent
  • Ability to grant assigned cability access to some agent
  • Ability to get cap claims received from other agents
  1. Go to the source code for the exercise.
  2. Implement all unimplemented!() functions in the exercise.
  3. Run npm test to test your implementation.

Relevant HDK documentation:

Solution

If you get stuck implementing this exercise, you can always look at its solution.