Cosmos - 账户体系介绍

Cosmos - 账户体系

Account

  • Cosmos中的账户被定义为一个接口类型,规定了一个账户类型所需要实现的一系列方法,包括对地址、公钥、序列号、账户号、资金的Get和Set方法。

    type Account interface {
    	GetAddress() sdk.AccAddress
    	SetAddress(sdk.AccAddress) error // errors if already set.
    
    	GetPubKey() crypto.PubKey // can return nil.
    	SetPubKey(crypto.PubKey) error
    
    	GetAccountNumber() uint64
    	SetAccountNumber(uint64) error
    
    	GetSequence() uint64
    	SetSequence(uint64) error
    
    	GetCoins() sdk.Coins
    	SetCoins(sdk.Coins) error
    
    	// Calculates the amount of coins that can be sent to other accounts given
    	// the current time.
    	SpendableCoins(blockTime time.Time) sdk.Coins
    
    	// Ensure that account implements stringer
    	String() string
    }
    

    BaseAccount

  • 实现了Account的接口的一个基本类型是BaseAccount,它包含了Account接口中方法的所需基本数据。

    // BaseAccount - a base account structure.
    // This can be extended by embedding within in your AppAccount.
    // However one doesn't have to use BaseAccount as long as your struct
    // implements Account.
    type BaseAccount struct {
    	Address       sdk.AccAddress `json:"address"`
    	Coins         sdk.Coins      `json:"coins"`
    	PubKey        crypto.PubKey  `json:"public_key"`
    	AccountNumber uint64         `json:"account_number"`
    	Sequence      uint64         `json:"sequence"`
    }
    
  • BaseAccount可以用来进行基础的转账、交易功能。一个基本账户对应了一个公钥(地址),但可以包含多个币种,这些币在该账户中的地位是等同的。另外,由于Cosmos本身属于账户体系,因此需要包含一个序列号,在每次交易时递增该序列号,防止之前的交易被攻击者拿来重放。 而account number是为了防止之前已经被减枝的账户的重放攻击(尽管目前cosmos还没有实现减枝功能)

  • 账户里的资金使用一个有序的Coin数组来组织资产,其中的每一个coin元素都对应一个不同币种,并依据denom进行排序,以支持对账户中资金的二分查找。

    type Coin struct {
    	Denom string `json:"denom"`
    
    	// To allow the use of unsigned integers (see: #1273) a larger refactor will
    	// need to be made. So we use signed integers for now with safety measures in
    	// place preventing negative values being used.
    	Amount Int `json:"amount"`
    }
    
  • 下面展示了cosmos-hub testnet上的一个基本账户,目前账户中的币有10000muon,由于该账户还未进行过转出交易(SequenceNumber为0),因此其公钥未知。

    Account:
      Address:       cosmos1hr5s6zhrtamefv6pya6qkug7hhgt7zcwew85tw
      Pubkey:
      Coins:         10000muon // balance
      AccountNumber: 1164
      Sequence:      0
    

    VestingAccount

  • VestingAccount在基本账户类型的基础上增加了允许账户中锁定币的定期解锁的功能,可以在创世区块中(Cosmos仅允许在genesis.json中使用该账户)包含此类账户。

  • VestingAccount也被定义为一个接口类型,BaseVestingAccount是它的一个基本实现:

    // VestingAccount defines an account type that vests coins via a vesting schedule.
    type VestingAccount interface {
    	Account
    
    	// Delegation and undelegation accounting that returns the resulting base
    	// coins amount.
    	TrackDelegation(blockTime time.Time, amount sdk.Coins)
    	TrackUndelegation(amount sdk.Coins)
    
    	GetVestedCoins(blockTime time.Time) sdk.Coins
    	GetVestingCoins(blockTime time.Time) sdk.Coins
    
    	GetStartTime() int64
    	GetEndTime() int64
    
    	GetOriginalVesting() sdk.Coins
    	GetDelegatedFree() sdk.Coins
    	GetDelegatedVesting() sdk.Coins
    }
    
    // BaseVestingAccount implements the VestingAccount interface. It contains all
    // the necessary fields needed for any vesting account implementation.
    type BaseVestingAccount struct {
        BaseAccount
    
        OriginalVesting  Coins // coins in account upon initialization
        DelegatedFree    Coins // coins that are vested and delegated
        DelegatedVesting Coins // coins that vesting and delegated
    
        EndTime  int64 // when the coins become unlocked
    }
    
  • 在BaseAccount的基础上,BaseVestingAccount需要定义初始锁定资金(OriginalVesting),已经delegate出去的已解锁的资金,以及已经delegate出去的未解锁的资金。Vesting account中所有币种(denomination)的币都以同样的速度解锁。而根据解锁方式的不同,VestingAccount又分为两类:离散型(DelayedVestingAccount,在某个时间之后一次性全部解锁)or 持续型(ContinuousVestingAccount,随着时间的增加持续解锁)。第一种账户定义了Endtime的值,在EndTime之后所有的币一次性解锁。第二种账户则定义了StartTime & EndTime,随着时间线性解锁。

  • // ContinuousVestingAccount implements the VestingAccount interface. It
    // continuously vests by unlocking coins linearly with respect to time.
    type ContinuousVestingAccount struct {
        BaseVestingAccount
    
        StartTime  int64 // when the coins start to vest
    }
    
    // DelayedVestingAccount implements the VestingAccount interface. It vests all
    // coins after a specific time, but non prior. In other words, it keeps them
    // locked until a specified time.
    type DelayedVestingAccount struct {
        BaseVestingAccount
    }
    
  • ContinuousVestingAccount示意图:

  • 处于锁定状态的币不能拿来转账、交易,但可以delegate给validator,来增加该validator的voting power,以从中获取收益。并且,在delegate时,优先级是VestingCoins>VestedCoins,即先看VestingCoins中的coin够不够,够的话全部从VestingCoins中出,不够的话再看VestedCoins。相反的,对已委托的coin进行回收时,优先级DelagetedFree>DelegatedVesting,

    Vesting Account:
      Address:          cosmos1wtv0kp6ydt03edd8kyr5arr4f3yc52vp5g7na0
      Pubkey:           cosmospub1addwnpepqd3xtcfgysaydlrs8hpaqeprdqua6wpx6dldklwwykgd9pq9c90vuea50zc
      Coins:            246681067muon
      AccountNumber:    391
      Sequence:         275
      OriginalVesting:  5000000000muon
      DelegatedFree:    10945770001muon
      DelegatedVesting:
      EndTime:          1518652800
    

    上图展示了一个Vesting Account,属于离散型解锁,其原始锁定的币为5000000000muon,已于2018年2月15日8:00全部解锁。目前delegate出去的币有10945770001muon。账户中目前可花的币有246681067muon。

    VestingAccount中可花费的资金的计算

  • 符号说明:

    OV(Original Vesting): 初始设置的vesting coin。
    V(Vesting): 尚未解锁的coin,该值并没有作为一个基本的account字段(为避免每个区块都要重新计算),而是根据需要进行计算。
    V’(Vested):已经解锁的coin。
    DV(Delegate Vesting): 授权出去的未解锁的coin。
    DF(Delegated Free/Vested): 授权出去的已经解锁的coin。
    BC(Base Coin): 即账户中的coins字段,包含了从其他地址转过来的可以花费的币、目前尚未授权出去的币(包括已解锁的和未解锁的)。

  • OV = V + V’

ContinuousVestingAccount的解锁方式,给定时间T:

  1. Compute X := T - StartTime
  2. Compute Y := EndTime - StartTime
  3. Compute V’ := OV * (X / Y)
  4. Compute V := OV - V’

DelayedVestingAccount的解锁方式,给定时间T:

  1. if T> EndTime V’=OV, V=0
  2. else V’=0, V=OV
  • 账户中可以自由花费的币的计算,由于BC中只有尚未解锁的未授权的币是不可花费的,因此只要减掉这部分,剩下的就是可以自由花费的:
    • ​ SpendableCoins=BC+DV-V

本文由 CoinEx Chain团队 JiaChase 写作,转载无需授权

1 Like