Skip to content

x/bank

Abstract

本文檔詳細說明了 bank 模塊

bank 模塊負責處理賬戶之間的多資產代幣轉賬,並跟踪特殊情況下的偽轉賬, 這些偽轉賬必須以不同的方式與特定類型的賬戶一起工作(特別是委託/取消委託的歸屬賬戶)。 它公開了幾個具有不同功能的接口,用於與必須改變用戶餘額的其他模塊進行安全交互。

此外,銀行模塊還跟踪並提供查詢支援,用於應用程式中使用的所有資產的總供應量。 例如,如果應用程式支援多種代幣,則銀行模塊可以提供查詢方法來獲取所有代幣的總供應量。 這可以幫助應用程式開發人員了解其應用程式中所有資產的總量,並監測是否存在超出預期的總供應量。

供應

supply 功能:

  • 被動地追蹤鏈內硬幣的總供應量,
  • 為模塊持有/與“Coins”交互提供模式,並引入不變量檢查以驗證鏈的總供應量。

總供應量

該網絡的總供應量等於所有賬戶中的所有代幣的總和。 每當一個代幣被鑄造(例如作為通脹機制的一部分)或銷毀(例如由於懲罰或如果治理提案被否決)時,總供應量都會更新。

模塊賬戶

供應功能引入了一種新型的 auth.Account ,模塊可以使用它來分配代幣,並在特殊情況下鑄造或燃燒代幣。 在基本層面上,這些模塊賬戶能夠向 auth.Account 和其他模塊賬戶發送/接收代幣。 這種設計取代了以前的替代設計,即為了持有代幣,模塊會燃燒來自發送方賬戶的傳入代幣,然後在內部跟踪這些代幣。 稍後,為了發送代幣,模塊需要在目標賬戶內有效地鑄造代幣。新設計消除了模塊之間重複的邏輯,以執行此會計。

ModuleAccount 接口定義如下:

type ModuleAccount interface {
  auth.Account               // same methods as the Account interface

  GetName() string           // name of the module; used to obtain the address
  GetPermissions() []string  // permissions of module account
  HasPermission(string) bool
}

WARNING! 任何允許直接或間接發送資金的模塊或消息處理器必須明確保證這些資金不能發送到模塊賬戶(除非允許)。

供應 Keeper 還為與 ModuleAccount 相關的 auth Keeper 和 bank Keeper 引入了新的包裝函數,以便能夠:

-通過提供 Name 來獲取和設置 ModuleAccount。 - 僅通過傳遞 Name 就可以將代幣從其他 ModuleAccount 或標准 Account 發送到其他賬戶。 - 為 ModuleAccount 鑄造或燃燒代幣(受其權限限制)。

權限

每個 ModuleAccount 都有一組不同的權限,這些權限提供了不同的對象功能以執行某些操作。 在創建供應 Keeper 時,需要註冊權限,以便每次 ModuleAccount 調用允許的函數時,Keeper 都可以查找特定賬戶的權限並執行或不執行操作。

可用的權限有:

  • Minter: 允許模組帳戶鑄造代幣。
  • Burner: 允許模組帳戶銷毀代幣。
  • Staking: 允許模組帳戶執行與權益證明相關的操作。

內容

狀態

x/bank 模塊主要維護三個主要對象的狀態,分別是賬戶餘額、資產元數據和所有餘額的總供應量。

  • 供應: 0x0 | byte(denom) -> byte(amount)
  • 資產元數據: 0x1 | byte(denom) -> ProtocolBuffer(Metadata)
  • 餘額: 0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)

Keepers

銀行模塊為其他模塊提供了導出的keeper接口,這些接口可以用來讀取或更新賬戶餘額。 在使用這些接口時,模塊應該選擇具有所需功能的最低權限接口。這樣做有助於確保模塊之間的安全性和隔離。

最佳實踐要求仔細審查bank模塊的代碼,以確保權限設置符合預期。 這樣可以避免潛在的安全風險,並確保模塊之間的正確協同。 在開發過程中,應該對代碼進行詳細檢查,確保權限限制得當。

封鎖地址(Blocklisting Addresses)

x/bank模塊接受一個地址map,這些地址被認為是被列入黑名單的, 無法通過如MsgSend以及直接API調用(如SendCoinsFromModuleToAccount)直接和明確地接收資金。

這意味著這些被列入黑名單的地址將被阻止從其他賬戶或模塊接收資金。 這有助於防止惡意行為或遵守監管要求,確保網絡的安全和穩定。然而,在實施這種限制時,應注意尊重用戶的隱私和權益,避免濫用封鎖功能。

通常,這些被列入黑名單的地址是模塊賬戶。如果這些地址在狀態機預期規則之外接收資金,很可能會破壞不變性,並可能導致網絡停止運行。

為了防止這種情況的發生,建議密切監控這些地址的資金接收情況,並確保其遵循狀態機的規則。 同時,建立有效的異常處理機制和安全策略,以防止這些地址在不符合狀態機規則的情況下接收資金。 這樣可以確保網絡的安全性和穩定性,防止潛在的網絡故障。

通過向x/bank模塊提供一組被列入黑名單的地址, 如果用戶或客戶端嘗試直接或間接向列入黑名單的賬戶發送資金,操作將會拋出一個錯誤。

這樣的設計可以防止被列入黑名單的地址通過各種途徑接收資金,確保網絡的安全性和合規性。 但在實施這些措施時,也需要注意遵循相關法律法規,尊重用戶的隱私和權益。 在設計和實施封鎖策略時,要確保其合理且不影響正常用戶的使用。

BaseKeeper

BaseKeeper 提供了完全的權限訪問:具有任意修改任何賬戶餘額以及鑄造或銷毀代幣的能力。 通過使用帶有 WithMintCoinsRestriction 的 BaseKeeper,可以實現對每個模組鑄幣權限的限制,從而給予特定的鑄幣限制(例如,僅鑄造特定面額的代幣)。這樣可以確保每個模組僅能按照預定的規則進行鑄幣操作,提高區塊鏈的安全性和可控性。

// Keeper 定義了一個模組接口,該接口有助於在賬戶之間實現代幣的轉移。
type Keeper interface {
    SendKeeper

    InitGenesis(sdk.Context, *types.GenesisState)
    ExportGenesis(sdk.Context) *types.GenesisState

    GetSupply(ctx sdk.Context, denom string) sdk.Coin
    GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error)
    IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool)
    GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool)
    SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
    IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)

    SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
    SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error
    SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
    DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
    UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
    MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
    BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error

    DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
    UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error

    types.QueryServer
}

SendKeeper

Send Keeper 提供對賬戶餘額的訪問以及在賬戶之間轉移代幣的功能。Send Keeper 不會改變代幣總供應量(即不會鑄造或銷毀代幣)。

// SendKeeper 定義了一個模組接口,該接口有助於在賬戶之間轉移代幣,而不具有創建代幣的可能性。
type SendKeeper interface {
    ViewKeeper

    InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
    SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error

    GetParams(ctx sdk.Context) types.Params
    SetParams(ctx sdk.Context, params types.Params)

    IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
    IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error

    BlockedAddr(addr sdk.AccAddress) bool
}

ViewKeeper

View Keeper 提供對賬戶餘額的只讀訪問。View Keeper 不具有修改餘額的功能。所有餘額查詢的時間複雜度都是 O(1)。

// ViewKeeper 定義了一個模組接口,該接口有助於實現對賬戶餘額的只讀訪問。
type ViewKeeper interface {
    ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) error
    HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool

    GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
    GetAccountsBalances(ctx sdk.Context) []types.Balance
    GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
    LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
    SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins

    IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(coin sdk.Coin) (stop bool))
    IterateAllBalances(ctx sdk.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool))
}

Messages

MsgSend

從一個地址向另一個地址發送代幣。 +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L19-L28

在以下情況下,消息將會失敗::

  • 代幣未啟用發送功能
  • to 地址受限

事件

銀行模組發出以下事件:

Handlers

MsgSend
Type Attribute Key Attribute Value
transfer recipient {recipientAddress}
transfer amount {amount}
message module bank
message action send
message sender {senderAddress}

Keeper events

In addition to handlers events, the bank keeper will produce events when the following methods are called (or any method which ends up calling them)

MintCoins
{
  "type": "coinbase",
  "attributes": [
    {
      "key": "minter",
      "value": "{{sdk.AccAddress of the module minting coins}}",
      "index": true
    },
    {
      "key": "amount",
      "value": "{{sdk.Coins being minted}}",
      "index": true
    }
  ]
}
{
  "type": "coin_received",
  "attributes": [
    {
      "key": "receiver",
      "value": "{{sdk.AccAddress of the module minting coins}}",
      "index": true
    },
    {
      "key": "amount",
      "value": "{{sdk.Coins being received}}",
      "index": true
    }
  ]
}
BurnCoins
{
  "type": "burn",
  "attributes": [
    {
      "key": "burner",
      "value": "{{sdk.AccAddress of the module burning coins}}",
      "index": true
    },
    {
      "key": "amount",
      "value": "{{sdk.Coins being burned}}",
      "index": true
    }
  ]
}
{
  "type": "coin_spent",
  "attributes": [
    {
      "key": "spender",
      "value": "{{sdk.AccAddress of the module burning coins}}",
      "index": true
    },
    {
      "key": "amount",
      "value": "{{sdk.Coins being burned}}",
      "index": true
    }
  ]
}
addCoins
{
  "type": "coin_received",
  "attributes": [
    {
      "key": "receiver",
      "value": "{{sdk.AccAddress of the address beneficiary of the coins}}",
      "index": true
    },
    {
      "key": "amount",
      "value": "{{sdk.Coins being received}}",
      "index": true
    }
  ]
}
subUnlockedCoins/DelegateCoins
{
  "type": "coin_spent",
  "attributes": [
    {
      "key": "spender",
      "value": "{{sdk.AccAddress of the address which is spending coins}}",
      "index": true
    },
    {
      "key": "amount",
      "value": "{{sdk.Coins being spent}}",
      "index": true
    }
  ]
}

參數

銀行模組包含以下參數:

Key Type Example
SendEnabled []SendEnabled [{denom: "stake", enabled: true }]
DefaultSendEnabled bool true

SendEnabled

send_enabled 參數是一個由 SendEnabled 條目組成的數組,將代幣面值映射到它們的 send_enabled 狀態。 此列表中的條目優先於 DefaultSendEnabled 設置。

DefaultSendEnabled

除非特別包含在 SendEnabled 參數的數組中,否則代幣面額不受影響。