一、委託人
在整個的cosmos中,委託人是一個非常重要的角色。通過委託機制可以達到全民參與的形式。這在EOS中也有體現。委託人,其實就是本身無力或者不想參與驗證過程的人,他們把自己的權益(代幣份額)交由某個人來代替執行自己的權益。
在整個的網絡中,驗證人的數量是有限的,正如美國大選,總統和議員總是少數,但是他們是由美國公民選舉出來的,可以把美國公民理解成委託人。當他們把票投給某個人時,某個人當選,然後當選的人就會有傾向性的做一些工作來回饋投票人。
在cosmos中,道理是相通的。
二、委託的流程
1、選擇驗證人
在委託前,還是要找一個利益最大化的驗證人來做爲自己的委託者。參照的信息包括:
驗證人的名稱、介紹、佣金變化率、最大佣金、最小抵押數量以及初始化佣金比例等。
2、委託人的說明
- 1)委託人應該對驗證人進行仔細調查,因爲一理驗證人有問題,相應的委託人會跟隨的被懲罰。
- 2)委託人在委託後也要積極監控驗證人,保證其合法進行工作,一旦有任何不滿意的地方,可以解綁並轉身另外一個驗證人。
- 3)委託人可以通過投票權來制衡他們的驗證人。
3、收益
在前面提到過爲了抵抗通貨膨脹,會定期的增發Atom分配給抵押者。這就是一種收益,那麼收益有哪些方面呢?
- 1)區塊增發的Atom獎勵。
- 2)區塊獎勵(photon)。比如對硬分叉的投票表決時會有獎勵。
- 3)交易費用,這個不用細說,幾乎所有的鏈都有這塊費用。
4、佣金
就如穩健型的投資一樣,每個驗證人的股權池會根據抵押比例獲取收益(利息)。不過,在將這筆收益按比例返給委託人時,驗證人有權抽取一筆佣金(手續費),換句話說,委託人想獲取收益,就必須向自己委託的驗證人提供一筆管理費。
這裏需要說明的是,佣金是委託人給予驗證人的。而收益是委託人拿到自己帳戶中的。
5、風險
把錢給別人用,這個風險是肯定有的。虛擬網絡和真實社會沒有什麼革命性的區別。那麼風險體現在哪兒呢?驗證人在行使權力的時候兒,Atom是被鎖倉的,首先沒辦法使用,再者,如果驗證人犯錯誤,Atom是要被罰減的。這裏面,就包含委託人的代幣。什麼原因會導致被處罰呢?
- 1)重複簽名:如果釣魚者反饋一個驗證人在多條鏈上的相同高度上多次簽名,那麼就會被懲罰。
- 2)不完成工作:也就是說不投票,佔着那個不那個。也會被懲罰。
- 3)玩失蹤:這和2有些類似。
三、源碼
委託人和驗證人以及stake相關的部分中會有很強的關係。
stake.go
// delegation bond for a delegated proof of stake system
type Delegation interface {
GetDelegator() Address // delegator address for the bond
GetValidator() Address // validator owner address for the bond
GetBondShares() Rat // amount of validator's shares
}
// properties for the set of all delegations for a particular
type DelegationSet interface {
// iterate through all delegations from one delegator by validator-address,
// execute func for each validator
IterateDelegators(Context, delegator Address,
fn func(index int64, delegation Delegation) (stop bool))
}
委託人的管理封裝數據結構。
delegation.go
// Delegation represents the bond with tokens held by an account. It is
// owned by one delegator, and is associated with the voting power of one
// pubKey.
// TODO better way of managing space
type Delegation struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorAddr sdk.Address `json:"validator_addr"`
Shares sdk.Rat `json:"shares"`
Height int64 `json:"height"` // Last height bond updated
}
func (b Delegation) equal(b2 Delegation) bool {
return bytes.Equal(b.DelegatorAddr, b2.DelegatorAddr) &&
bytes.Equal(b.ValidatorAddr, b2.ValidatorAddr) &&
b.Height == b2.Height &&
b.Shares.Equal(b2.Shares)
}
// ensure fulfills the sdk validator types
var _ sdk.Delegation = Delegation{}
// nolint - for sdk.Delegation
func (b Delegation) GetDelegator() sdk.Address { return b.DelegatorAddr }
func (b Delegation) GetValidator() sdk.Address { return b.ValidatorAddr }
func (b Delegation) GetBondShares() sdk.Rat { return b.Shares }
//Human Friendly pretty printer
func (b Delegation) HumanReadableString() (string, error) {
bechAcc, err := sdk.Bech32ifyAcc(b.DelegatorAddr)
if err != nil {
return "", err
}
bechVal, err := sdk.Bech32ifyAcc(b.ValidatorAddr)
if err != nil {
return "", err
}
resp := "Delegation \n"
resp += fmt.Sprintf("Delegator: %s\n", bechAcc)
resp += fmt.Sprintf("Validator: %s\n", bechVal)
resp += fmt.Sprintf("Shares: %s", b.Shares.String())
resp += fmt.Sprintf("Height: %d", b.Height)
return resp, nil
}
這裏需要在處理的handle中控制綁定的委託者和驗證人
handler.go
// common functionality between handlers
func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address,
bondAmt sdk.Coin, validator Validator) (sdk.Tags, sdk.Error) {
// Get or create the delegator bond
bond, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner)
if !found {
bond = Delegation{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validator.Owner,
Shares: sdk.ZeroRat(),
}
}
// Account new shares, save
pool := k.GetPool(ctx)
_, _, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{bondAmt})
if err != nil {
return nil, err
}
validator, pool, newShares := validator.addTokensFromDel(pool, bondAmt.Amount)
bond.Shares = bond.Shares.Add(newShares)
// Update bond height
bond.Height = ctx.BlockHeight()
k.setPool(ctx, pool)
k.setDelegation(ctx, bond)
k.updateValidator(ctx, validator)
tags := sdk.NewTags("action", []byte("delegate"), "delegator", delegatorAddr.Bytes(), "validator", validator.Owner.Bytes())
return tags, nil
}
將委託者和驗證人綁定在一起是通過Msg的bond和unbond來實現的。
msg.go
// MsgDelegate - struct for bonding transactions
type MsgDelegate struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorAddr sdk.Address `json:"validator_addr"`
Bond sdk.Coin `json:"bond"`
}
func NewMsgDelegate(delegatorAddr, validatorAddr sdk.Address, bond sdk.Coin) MsgDelegate {
return MsgDelegate{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
Bond: bond,
}
}
// MsgUnbond - struct for unbonding transactions
type MsgUnbond struct {
DelegatorAddr sdk.Address `json:"delegator_addr"`
ValidatorAddr sdk.Address `json:"validator_addr"`
Shares string `json:"shares"`
}
func NewMsgUnbond(delegatorAddr, validatorAddr sdk.Address, shares string) MsgUnbond {
return MsgUnbond{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
Shares: shares,
}
}
四、總結
通過上面的分析和說明,可以看出,委託人其實就是普通的網絡節點,驗證人的資格也不是你想有就有的。POS的機制決定了跟和資本主義社會一樣,沒有足夠的金錢,沒法參加大選。
這也是POS飽受詬病的地方,在COSMOS中也有一些防止的方法,但目前看來還不能從根本上解決問題。所以委託人在委託時,還是不要任性。