0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Capabilities

Last updated at Posted at 2024-10-24

アカウントには、それと関連付けられたCapabilityがあります。

アカウントは、capabilitiesフィールドを通じてそのCapabilityを公開しています。このフィールドの型は、Account.Capabilitiesです。

Account.Capabilities

access(all)
struct Capabilities {

    /// The storage capabilities of the account.
    access(mapping CapabilitiesMapping)
    let storage: Account.StorageCapabilities

    /// The account capabilities of the account.
    access(mapping CapabilitiesMapping)
    let account: Account.AccountCapabilities

    /// Returns the capability at the given public path.
    /// If the capability does not exist,
    /// or if the given type is not a supertype of the capability's borrow type,
    /// returns an "invalid" capability with ID 0 that will always fail to `check` or `borrow`
    access(all)
    view fun get<T: &Any>(_ path: PublicPath): Capability<T>

    /// Borrows the capability at the given public path.
    /// Returns nil if the capability does not exist, or cannot be borrowed using the given type.
    /// The function is equivalent to `get(path).borrow()`.
    access(all)
    view fun borrow<T: &Any>(_ path: PublicPath): T?

    /// Returns true if a capability exists at the given public path.
    access(all)
    view fun exists(_ path: PublicPath): Bool

    /// Publish the capability at the given public path.
    ///
    /// If there is already a capability published under the given path, the program aborts.
    ///
    /// The path must be a public path, i.e., only the domain `public` is allowed.
    access(Capabilities | PublishCapability)
    fun publish(_ capability: Capability, at: PublicPath)

    /// Unpublish the capability published at the given path.
    ///
    /// Returns the capability if one was published at the path.
    /// Returns nil if no capability was published at the path.
    access(Capabilities | UnpublishCapability)
    fun unpublish(_ path: PublicPath): Capability?
}

entitlement Capabilities

entitlement PublishCapability
entitlement UnpublishCapability

Checking the existence of public capabilities

capabilities.check関数は、指定されたパスで以前にpublic Capabilityが保存されていたかどうかを判断します。

access(all)
view fun exists(_ path: PublicPath): Bool

アカウントが指定されたパスでCapabilityを持っている場合、関数は true を返し、そうでない場合は false を返します。

Getting public capabilities

capabilities.get関数は、保存されているpublic Capabilityを取得します。

access(all)
view fun get<T: &Any>(_ path: PublicPath): Capability<T>

アカウントが指定されたパス且つ指定されたタイプのCapabilityを持っている場合、関数はそれを返します。

アカウントが指定されたパスで保存しているCapabilityがない場合、または指定されたタイプがCapabilityのborrow typeのスーパータイプでない場合、関数はIDが0の「無効」なCapabilityを返します。このCapabilityは、checkまたはborrowを行うときに常に失敗します。

便利関数capabilities.borrowは、以前に保存されたpublic Capabilityを1アクションで取得および借用します。

access(all)
view fun borrow<T: &Any>(_ path: PublicPath): T?

アカウントが指定されたパス且つ指定されたタイプのCapabilityを保存している場合、関数はそのCapabilityを借用し、その結果の参照(reference)をオプショナルとして返します。

アカウントが指定されたパスでCapabilityを保存していない場合、もしくは、型パラメータTで要求されたタイプが保存されたCapabilityのものと一致しない場合、関数はnilを返します。

Managing capabilities

Capabilityには、Storage CapabilityとAccount Capabilityの2種類があります。

  • ストレージCapabilityは、パス(paths)を介して、アカウントの持つストレージ内のオブジェクトへのアクセスを許可します。アカウントは、capabilities.storageフィールド(タイプは* Account.StorageCapabilitiesになります)によって、ストレージCapabilityの管理が可能です。
  • アカウントCapabilityは、Accountへのアクセスを許可します。アカウントは、capabilities.accountフィールド(タイプはAccount.AccountCapabilitiesになります)によって、アカウントCapabilityの管理が可能です。

Capabilityおよびそのすべてのコピーは、Capability controllerによって管理されます。

  • ストレージCapabilityはストレージCapabilityコントローラによって制御されます(原文: are controlled)。ストレージCapabilityコントローラの型はStorageCapabilityControllerです。
  • アカウントCapabilityはアカウントCapabilityコントローラによって制御されます。アカウントCapabilityコントローラの型はAccountCapabilityControllerです。

Account.StorageCapabilities and Account.AccountCapabilities

access(all)
struct StorageCapabilities {

    /// Issue/create a new storage capability.
    access(Capabilities | StorageCapabilities | IssueStorageCapabilityController)
    fun issue<T: &Any>(_ path: StoragePath): Capability<T>

    /// Issue/create a new storage capability.
    access(Capabilities | StorageCapabilities | IssueStorageCapabilityController)
    fun issueWithType(_ path: StoragePath, type: Type): Capability

    /// Get the storage capability controller for the capability with the specified ID.
    ///
    /// Returns nil if the ID does not reference an existing storage capability.
    access(Capabilities | StorageCapabilities | GetStorageCapabilityController)
    view fun getController(byCapabilityID: UInt64): &StorageCapabilityController?

    /// Get all storage capability controllers for capabilities that target this storage path
    access(Capabilities | StorageCapabilities | GetStorageCapabilityController)
    view fun getControllers(forPath: StoragePath): [&StorageCapabilityController]

    /// Iterate over all storage capability controllers for capabilities that target this storage path,
    /// passing a reference to each controller to the provided callback function.
    ///
    /// Iteration is stopped early if the callback function returns `false`.
    ///
    /// If a new storage capability controller is issued for the path,
    /// an existing storage capability controller for the path is deleted,
    /// or a storage capability controller is retargeted from or to the path,
    /// then the callback must stop iteration by returning false.
    /// Otherwise, iteration aborts.
    access(Capabilities | StorageCapabilities | GetStorageCapabilityController)
    fun forEachController(
        forPath: StoragePath,
        _ function: fun(&StorageCapabilityController): Bool
    )
}

access(all)
struct AccountCapabilities {

    /// Issue/create a new account capability.
    access(Capabilities | AccountCapabilities | IssueAccountCapabilityController)
    fun issue<T: &Account>(): Capability<T>

    /// Issue/create a new account capability.
    access(Capabilities | AccountCapabilities | IssueAccountCapabilityController)
    fun issueWithType(_ type: Type): Capability

    /// Get capability controller for capability with the specified ID.
    ///
    /// Returns nil if the ID does not reference an existing account capability.
    access(Capabilities | AccountCapabilities | GetAccountCapabilityController)
    view fun getController(byCapabilityID: UInt64): &AccountCapabilityController?

    /// Get all capability controllers for all account capabilities.
    access(Capabilities | AccountCapabilities | GetAccountCapabilityController)
    view fun getControllers(): [&AccountCapabilityController]

    /// Iterate over all account capability controllers for all account capabilities,
    /// passing a reference to each controller to the provided callback function.
    ///
    /// Iteration is stopped early if the callback function returns `false`.
    ///
    /// If a new account capability controller is issued for the account,
    /// or an existing account capability controller for the account is deleted,
    /// then the callback must stop iteration by returning false.
    /// Otherwise, iteration aborts.
    access(Capabilities | AccountCapabilities | GetAccountCapabilityController)
    fun forEachController(_ function: fun(&AccountCapabilityController): Bool)
}

entitlement StorageCapabilities
entitlement AccountCapabilities

entitlement GetStorageCapabilityController
entitlement IssueStorageCapabilityController

entitlement GetAccountCapabilityController
entitlement IssueAccountCapabilityController

entitlement mapping CapabilitiesMapping {
    include Identity

    StorageCapabilities -> GetStorageCapabilityController
    StorageCapabilities -> IssueStorageCapabilityController

    AccountCapabilities -> GetAccountCapabilityController
    AccountCapabilities -> IssueAccountCapabilityController
}

AccountCapabilityController and StorageCapabilityController

access(all)
struct AccountCapabilityController {

    /// The capability that is controlled by this controller.
    access(all)
    let capability: Capability

    /// An arbitrary "tag" for the controller.
    /// For example, it could be used to describe the purpose of the capability.
    /// Empty by default.
    access(all)
    var tag: String

    /// Updates this controller's tag to the provided string
    access(all)
    fun setTag(_ tag: String)

    /// The type of the controlled capability, i.e. the T in `Capability<T>`.
    access(all)
    let borrowType: Type

    /// The identifier of the controlled capability.
    /// All copies of a capability have the same ID.
    access(all)
    let capabilityID: UInt64

    /// Delete this capability controller,
    /// and disable the controlled capability and its copies.
    ///
    /// The controller will be deleted from storage,
    /// but the controlled capability and its copies remain.
    ///
    /// Once this function returns, the controller is no longer usable,
    /// all further operations on the controller will panic.
    ///
    /// Borrowing from the controlled capability or its copies will return nil.
    ///
    access(all)
    fun delete()
}
access(all)
struct StorageCapabilityController {

    /// The capability that is controlled by this controller.
    access(all)
    let capability: Capability

    /// An arbitrary "tag" for the controller.
    /// For example, it could be used to describe the purpose of the capability.
    /// Empty by default.
    access(all)
    var tag: String

    /// Updates this controller's tag to the provided string
    access(all)
    fun setTag(_ tag: String)

    /// The type of the controlled capability, i.e. the T in `Capability<T>`.
    access(all)
    let borrowType: Type

    /// The identifier of the controlled capability.
    /// All copies of a capability have the same ID.
    access(all)
    let capabilityID: UInt64

    /// Delete this capability controller,
    /// and disable the controlled capability and its copies.
    ///
    /// The controller will be deleted from storage,
    /// but the controlled capability and its copies remain.
    ///
    /// Once this function returns, the controller is no longer usable,
    /// all further operations on the controller will panic.
    ///
    /// Borrowing from the controlled capability or its copies will return nil.
    ///
    access(all)
    fun delete()

    /// Returns the targeted storage path of the controlled capability.
    access(all)
    fun target(): StoragePath

    /// Retarget the controlled capability to the given storage path.
    /// The path may be different or the same as the current path.
    access(all)
    fun retarget(_ target: StoragePath)
}

Issuing capabilities

Capabilityは、対象アカウントの中に発行することで作成されます。

ストレージCapabilityの発行

capabilities.storage.issue関数は、指定したストレージpathを対象とし、指定したタイプで借用できる新しいストレージCapabilityを発行します。

access(Capabilities | StorageCapabilities | IssueStorageCapabilityController)
fun issue<T: &Any>(_ path: StoragePath): Capability<T>

issue関数を呼び出すには、粗粒度のCapabilities権限またはStorageCapabilities権限(auth(Capabilities) &Accountまたはauth(StorageCapabilities) &Account)または、細粒度のIssueStorageCapabilityController権限(auth(IssueStorageCapabilityController) &Account)で認証された参照経由でアカウントにアクセスする必要があります。

pathはストレージパスでなければならず、domain storageを持っていなければなりません。

例えば、以下のトランザクションは、必要なWithdraw権限で借用されるCapabilityを認証することで、保存されたvaultから引き出す(withdraw)権限を付与する新しいストレージCapabilityを発行します。(補足: 要はリソース(資産)を引き出す権限のあるCapabilityを作るということ)

transaction {
    prepare(signer: auth(IssueStorageCapabilityController) &Account) {
        let capability = signer.capabilities.storage.issue<auth(Withdraw) &Vault>(/storage/vault)
        // ...
    }
}

アカウントCapabilityの発行

capabilities.account.issue 関数は、アカウントを対象にした、指定したタイプで借用できる、新しいアカウントCapabilityを発行します。

access(Capabilities | AccountCapabilities | IssueAccountCapabilityController)
fun issue<T: &Account>(): Capability<T>

issue関数を呼び出すには、粗粒度のCapabilities権限またはAccountCapabilities権限(auth(Capabilities) &Accountまたはauth(AccountCapabilities) &Account)または、細粒度のIssueAccountCapabilityController権限(auth(IssueAccountCapabilityController) &Account)で認証された参照経由でアカウントにアクセスする必要があります。

例えば、次のトランザクションは、必要なSaveValue権限で借用されるCapabilityを認証することで、アカウントにオブジェクトを保存する能力を付与する(原文: grants the ability to save)、新しいアカウントCapabilityを発行します。

transaction {
    prepare(signer: auth(IssueAccountCapabilityController) &Account) {
        let capability = signer.capabilities.account.issue<auth(SaveValue) &Account>()
        // ...
    }
}

Publishing capabilities

Capabilityは、それをpublishすることで一般に公開することができます。

capabilities.publish関数は、指定されたpublic pathでCapabilityをpublishします。

access(Capabilities | PublishCapability)
fun publish(_ capability: Capability, at: PublicPath)

publish関数を呼び出すには、粗粒度のCapabilities権限(auth(Capabilities) &Account)または、細粒度のPublishCapability権限(auth(PublishCapability) &Account)で認証された参照を介してアカウントにアクセスする必要があります

例えば、以下のトランザクションでは、新しいストレージCapabilityを発行し、パス/public/vaultの下でそれをpublishします。これにより、誰でもそのCapabilityにアクセスしてborrowし、格納されたvaultにアクセスできるようになります。補足: 参照(reference)タイプは認証されていないため、Capabilityがborrowされた場合、公開されている(access(all))フィールドとオブジェクトの関数のみにアクセスできます。(補足: 本人以外書き換え権限はありません)

transaction {
    prepare(signer: auth(Capabilities) &Account) {
        let capability = signer.capabilities.storage.issue<&Vault>(/storage/vault)
        signer.capabilities.publish(capability, at: /public/vault)
    }
}

Unpublishing capabilities

capabilities.unpublish関数は、指定されたpublic pathからCapabilityを解除(unpublish)します。

access(Capabilities | UnpublishCapability)
fun unpublish(_ path: PublicPath): Capability?

unpublish関数を呼び出すには、粗粒度のCapabilities権限(auth(Capabilities) &Account)で認証された参照経由でアカウントにアクセスするか、または、細粒度のUnpublishCapability権限(auth(UnpublishCapability) &Account)で認証された参照経由でアカウントにアクセスする必要があります。

パスで保存されているCapabilityがある場合、そのCapabilityはパスから削除され、返されます。パスで保存されている機能がない場合、この関数はnilを返します。

例えば、以下のトランザクションは、パス/public/vaultで保存されたCapabilityを解除します。

transaction {
    prepare(signer: auth(Capabilities) &Account) {
        signer.capabilities.unpublish(/public/vault)
    }
}

Tagging capabilities

Capabilityには任意の文字列であるタグを関連付けることができます。タグは、Capabilityの目的を記録するなど、さまざまな目的で使用できます。デフォルトでは空です。タグはCapability controllerに保存されます。

ストレージCapabilityコントローラ(StorageCapabilityController)とアカウントCapabilityコントローラ(AccountCapabilityController)の両方に、tagフィールドとsetTag関数が用意されており、これを使用してタグを取得したり設定したりすることができます。

access(all)
var tag: String

access(all)
fun setTag(_ tag: String)

Retargeting storage capabilities

ストレージCapability(StorageCapabilityController)は、発行(保存)後に別のstorage pathに再ターゲットできます。

target関数は制御されたCapabilityのstorage pathを返し、retarget関数は新しいstorage pathを設定します。

access(all)
fun target(): StoragePath

access(all)
fun retarget(_ target: StoragePath)

Revoking capabilities

Capabilityおよびそのすべてのコピーは、Capabilityのコントローラーを削除することで取り消すことができます。

delete関数は、コントローラー(StorageCapabilityControllerまたはAccountCapabilityController)を削除します。

access(all)
fun delete()

Getting capability controllers

StorageCapabilitiesおよびAccountCapabilitiesというCapability managementタイプにより、Capabilityのコントローラを取得できるだけでなく、既存のすべてのコントローラを順に取得することもできます。

ストレージCapabilityコントローラの取得
capabilities.storage.getController関数は、指定されたCapability IDのCapabilityに対応するストレージCapabilityコントローラを取得します。

access(Capabilities | StorageCapabilities | GetStorageCapabilityController)
view fun getController(byCapabilityID: UInt64): &StorageCapabilityController?

getController 関数を呼び出すには、粗粒度のCapabilities権限またはStorageCapabilities権限(auth(Capabilities) &Accountまたはauth(StorageCapabilities) &Account)で認証された参照によるアカウントへのアクセス、または、細粒度のGetStorageCapabilityController権限(auth(GetStorageCapabilityController) &Account)が必要です。

指定されたIDのCapabilityに対応するストレージCapabilityコントローラが存在する場合は、オプショナルとしてその参照が返されます。指定されたCapability IDに対応するストレージCapabilityコントローラが存在しない場合は、この関数はnilを返します。

アカウントCapabilityコントローラの取得
capabilities.account.getController関数は、指定されたCapability IDに対応するアカウントCapabilityコントローラを取得します。

access(Capabilities | AccountCapabilities | GetAccountCapabilityController)
view fun getController(byCapabilityID: UInt64): &AccountCapabilityController?

getController 関数を呼び出すには、粗粒度のCapabilities権限またはAccountCapabilities権限(auth(Capabilities) &Accountまたはauth(AccountCapabilities) &Account)で認証された参照によるアカウントへのアクセス、または、細粒度のGetAccountCapabilityController権限(auth(GetAccountCapabilityController) &Account)が必要です。

指定したIDのCapabilityに対応するアカウントCapabilityコントローラが存在する場合、この関数はオプショナルとしてその参照を返します。指定したCapability IDに対応するアカウントCapabilityコントローラが存在しない場合、この関数はnilを返します。

ストレージCapabilityコントローラの反復処理
関数getControllersおよびforEachControllerを使用すると、ストレージパスのすべてのストレージCapabilityコントローラを反復処理できます。

access(Capabilities | StorageCapabilities | GetStorageCapabilityController)
view fun getControllers(forPath: StoragePath): [&StorageCapabilityController]

access(Capabilities | StorageCapabilities | GetStorageCapabilityController)
fun forEachController(
    forPath: StoragePath,
    _ function: fun(&StorageCapabilityController): Bool
)

getControllersおよびforEachController関数を呼び出すには、粗粒度のCapabilities権限またはStorageCapabilities権限(auth(Capabilities) &Accountまたはauth(StorageCapabilities) &Account)で認証された参照によるアカウントへのアクセス、または、細粒度のGetStorageCapabilityController権限(auth(GetStorageCapabilityController) &Account)が必要です。

getControllers関数は、すべてのストレージCapabilityコントローラへの参照の新しい配列を返します。

forEachController関数は、各ストレージCapabilityコントローラに対して指定のコールバック関数を呼び出し、その関数への参照を渡します。コールバック関数がfalseを返すと、反復処理が停止します。

アカウントCapabilityコントローラの反復処理
getControllers関数およびforEachController関数を使用すると、アカウントのすべてのアカウントCapabilityコントローラを反復処理できます。

access(Capabilities | AccountCapabilities | GetAccountCapabilityController)
view fun getControllers(): [&AccountCapabilityController]

access(Capabilities | AccountCapabilities | GetAccountCapabilityController)
fun forEachController(_ function: fun(&AccountCapabilityController): Bool)

getControllers関数およびforEachController関数を呼び出すには、粗粒度のCapabilities権限またはAccountCapabilities権限(auth(Capabilities) &Accountまたはauth(AccountCapabilities) &Account)または、細粒度のGetAccountCapabilityController権限(auth(GetAccountCapabilityController) &Account)で認証された参照によるアカウントへのアクセスが必要です。

getControllers関数は、すべてのアカウントCapabilityコントローラへの参照の新しい配列を返します。

forEachController関数は、各アカウントCapabilityコントローラに対して指定のコールバック関数を呼び出し、その関数への参照を渡します。コールバック関数がfalseを返すと、繰り返し処理が停止します。

Example

entitlement Increment

// Declare a resource named `Counter` that has a field `count`
// and a function `increment`, which requires the `Increment` entitlement.
//
access(all)
resource Counter {

    access(all)
    var count: UInt

    access(all)
    init(count: UInt) {
        self.count = count
    }

    access(Increment)
    fun increment(by amount: UInt) {
        self.count = self.count + amount
    }
}

// In this example an account reference is available through the constant `account`,
// which has the type `auth(Storage, Capabilities) &Account`,
// i.e., the reference is authorized to perform storage and capability operations.

// Create a new instance of the resource type `Counter`
// and save it in the storage of the account.
//
// The path `/storage/counter` is used to refer to the stored value.
// Its identifier `counter` was chosen freely and could be something else.
//
account.storage.save(
    <-create Counter(count: 42),
    to: /storage/counter
)

// Issue a new storage capability that allows access to the stored counter resource
//
let capability = account.capabilities.storage.issue<&Counter>(/storage/counter)

// Publish the capability under the path `/public/counter`,
// so that anyone can access the counter resource.
//
// Its identifier `counter` was chosen freely and could be something else.
//
account.capabilities.publish(capability, at: /public/counter)

次に示す例は、異なるコンテクスト(例えば新しい script や transaction)での例であると想像してください。


// Get a reference to the account that stores the counter
//
let account = getAccount(0x1)

// Borrow the capability for the counter that is made publicly accessible
// through the path `/public/counter`.
//
// The call of `borrow` returns an optional reference `&Counter?`.
// The borrow succeeds, and the result is not `nil`,
// it is a valid reference, because:
//
// 1. The path `/public/counter` stores a capability.
//
// 2. The capability allows to be borrowed as `&Counter`,
//    as it has the type `Capability<&Counter>`.
//
// 3. The target of the storage capability, the *path* `/storage/counter`,
//    stores an object and it has a type which is a subtype of the borrowed type
//    (type equality is also considered a subtype relationship).
//
// Finally, force-unwrap the optional reference.
// After the call, the declared constant `counterRef` has type `&Counter`.
//
let counterRef = account.capabilities.borrow<&Counter>(/public/counter)!

// Read the field `count` of the `Counter`.
// The field can be accessed, because it has the access modifier `access(all)`.
//
// Even though it is a variable field (`var`),
// it cannot be assigned to from outside of the object.
//
counterRef.count  // is `42`

// Invalid: The `increment` function is not accessible for the reference,
// because the reference has the type `&Counter`,
// which does not authorize the entitlement `Increment`,
// which is required by the `increment` function
// (it has the access modifier ` access(Increment)`).
//
counterRef.increment(by: 5)

// Again, attempt to borrow the capability for the counter,
// but use the type `auth(Increment) &Counter` to re-attempt the call to `increment`.
//
// Getting the capability fails, because the capability was issued using the type `&Counter`.
// After the call, `counterRef2` is `nil`.
//
let counterRef2 = account.capabilities.borrow<auth(Increment) &Counter>(/public/counter)

翻訳元->https://cadence-lang.org/docs/language/accounts/capabilities

Flow BlockchainのCadence version1.0ドキュメント (Capabilities)

Previous << Storage

Next >> Keys

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?