x/auth module spec / code reconciliation (#2964)

This commit is contained in:
Christopher Goes 2018-12-06 01:48:08 +01:00 committed by Jack Zampolin
parent 816248987f
commit ba5e87ca6f
8 changed files with 239 additions and 4 deletions

View File

@ -43,7 +43,8 @@ IMPROVEMENTS
* Gaia
* SDK
* \#1277 Complete bank module specification
- \#1277 Complete bank module specification
- \#2963 Complete auth module specification
* \#2914 No longer withdraw validator rewards on bond/unbond, but rather move
the rewards to the respective validator's pools.

29
docs/spec/auth/README.md Normal file
View File

@ -0,0 +1,29 @@
# Auth module specification
## Abstract
This document specifies the auth module of the Cosmos SDK.
The auth module is responsible for specifying the base transaction and account types
for an application, since the SDK itself is agnostic to these particulars. It contains
the ante handler, where all basic transaction validity checks (signatures, nonces, auxiliary fields)
are performed, and exposes the account keeper, which allows other modules to read, write, and modify accounts.
This module will be used in the Cosmos Hub.
## Contents
1. **[State](state.md)**
1. [Accounts](state.md#accounts)
1. [Account Interface](state.md#account-interface)
1. [Base Account](state.md#baseaccount)
1. [Vesting Account](state.md#vestingaccount)
1. **[Types](types.md)**
1. [StdFee](types.md#stdfee)
1. [StdSignature](types.md#stdsignature)
1. [StdTx](types.md#stdtx)
1. [StdSignDoc](types.md#stdsigndoc)
1. **[Keepers](keepers.md)**
1. [AccountKeeper](keepers.md#account-keeper)
1. **[Handlers](handlers.md)**
1. [Ante Handler](handlers.md#ante-handler)

View File

@ -0,0 +1,38 @@
## Handlers
The auth module presently has no transaction handlers of its own, but does expose
the special `AnteHandler`, used for performing basic validity checks on a transaction,
such that it could be thrown out of the mempool. Note that the ante handler is called on
`CheckTx`, but *also* on `DeliverTx`, as Tendermint proposers presently have the ability
to include in their proposed block transactions which fail `CheckTx`.
### Ante Handler
```golang
anteHandler(ak AccountKeeper, fck FeeCollectionKeeper, tx sdk.Tx)
if !tx.(StdTx)
fail with "not a StdTx"
if isCheckTx and tx.Fee < config.SubjectiveMinimumFee
fail with "insufficient fee for mempool inclusion"
if tx.ValidateBasic() != nil
fail with "tx failed ValidateBasic"
if tx.Fee > 0
account = GetAccount(tx.GetSigners()[0])
coins := acount.GetCoins()
if coins < tx.Fee
fail with "insufficient fee to pay for transaction"
account.SetCoins(coins - tx.Fee)
fck.AddCollectedFees(tx.Fee)
for index, signature in tx.GetSignatures()
account = GetAccount(tx.GetSigners()[index])
bytesToSign := StdSignBytes(chainID, acc.GetAccountNumber(),
acc.GetSequence(), tx.Fee, tx.Msgs, tx.Memo)
if !signature.Verify(bytesToSign)
fail with "invalid signature"
return
```

39
docs/spec/auth/keepers.md Normal file
View File

@ -0,0 +1,39 @@
## Keepers
The auth module only exposes one keeper, the account keeper, which can be used to read and write accounts.
### Account Keeper
Presently only one fully-permissioned account keeper is exposed, which has the ability to both read and write
all fields of all accounts, and to iterate over all stored accounts.
```golang
type AccountKeeper interface {
// Return a new account with the next account number and the specified address. Does not save the new account to the store.
NewAccountWithAddress(AccAddress) Account
// Return a new account with the next account number. Does not save the new account to the store.
NewAccount(Account) Account
// Retrieve an account from the store
GetAccount(AccAddress) Account
// Set an account in the store
SetAccount(Account)
// Remove an account from the store
RemoveAccount(Account)
// Iterate over all accounts, calling the provided function. Stop iteraiton when it returns false.
IterateAccounts(func(Account) (bool))
// Fetch the public key of an account at a specified address
GetPubKey(AccAddress) PubKey
// Fetch the sequence of an account at a specified address
GetSequence(AccAddress) uint64
// Fetch the next account number, and increment the internal counter
GetNextAccountNumber() uint64
}
```

View File

@ -0,0 +1,58 @@
## State
### Accounts
Accounts contain authentication information for a uniquely identified external user of an SDK blockchain,
including public key, address, and account number / sequence number for replay protection. For efficiency,
since account balances must also be fetched to pay fees, account structs also store the balance of a user
as `sdk.Coins`.
Accounts are exposed externally as an interface, and stored internally as
either a base account or vesting account. Module clients wishing to add more
account types may do so.
- `0x01 | Address -> amino(account)`
#### Account Interface
The account interface exposes methods to read and write standard account information.
Note that all of these methods operate on an account struct confirming to the interface
- in order to write the account to the store, the account keeper will need to be used.
```golang
type Account interface {
GetAddress() AccAddress
SetAddress(AccAddress)
GetPubKey() PubKey
SetPubKey(PubKey)
GetAccountNumber() uint64
SetAccountNumber(uint64)
GetSequence() uint64
SetSequence(uint64)
GetCoins() Coins
SetCoins(Coins)
}
```
#### Base Account
A base account is the simplest and most common account type, which just stores all requisite
fields directly in a struct.
```golang
type BaseAccount struct {
Address AccAddress
Coins Coins
PubKey PubKey
AccountNumber uint64
Sequence uint64
}
```
#### Vesting Account
See [Vesting](vesting.md).

65
docs/spec/auth/types.md Normal file
View File

@ -0,0 +1,65 @@
## Types
Besides accounts (specified in [State](state.md)), the types exposed by the auth module
are `StdFee`, the combination of an amount and gas limit, `StdSignature`, the combination
of an optional public key and a cryptographic signature as a byte array, `StdTx`,
a struct which implements the `sdk.Tx` interface using `StdFee` and `StdSignature`, and
`StdSignDoc`, a replay-prevention structure for `StdTx` which transaction senders must sign over.
### StdFee
A `StdFee` is simply the combination of a fee amount, in any number of denominations,
and a gas limit (where dividing the amount by the gas limit gives a "gas price").
```golang
type StdFee struct {
Amount Coins
Gas uint64
}
```
### StdSignature
A `StdSignature` is the combination of an optional public key and a cryptographic signature
as a byte array. The SDK is agnostic to particular key or signature formats and supports any
supported by the `PubKey` interface.
```golang
type StdSignature struct {
PubKey PubKey
Signature []byte
}
```
### StdTx
A `StdTx` is a struct which implements the `sdk.Tx` interface, and is likely to be generic
enough to serve the purposes of many Cosmos SDK blockchains.
```golang
type StdTx struct {
Msgs []sdk.Msg
Fee StdFee
Signatures []StdSignature
Memo string
}
```
### StdSignDoc
A `StdSignDoc` is a replay-prevention structure to be signed over, which ensures that
any submitted transaction (which is simply a signature over a particular bytestring)
will only be executable once on a particular blockchain.
`json.RawMessage` is preferred over using the SDK types for future compatibility.
```golang
type StdSignDoc struct {
AccountNumber uint64
ChainID string
Fee json.RawMessage
Memo string
Msgs []json.RawMessage
Sequence uint64
}
```

View File

@ -6,7 +6,12 @@ import (
"github.com/tendermint/tendermint/crypto"
)
var globalAccountNumberKey = []byte("globalAccountNumber")
var (
// Prefix for account-by-address store
AddressStoreKeyPrefix = []byte{0x01}
globalAccountNumberKey = []byte("globalAccountNumber")
)
// This AccountKeeper encodes/decodes accounts using the
// go-amino (binary) encoding/decoding library.
@ -61,7 +66,7 @@ func (am AccountKeeper) NewAccount(ctx sdk.Context, acc Account) Account {
// Turn an address to key used to get it from the account store
func AddressStoreKey(addr sdk.AccAddress) []byte {
return append([]byte("account:"), addr.Bytes()...)
return append(AddressStoreKeyPrefix, addr.Bytes()...)
}
// Implements sdk.AccountKeeper.
@ -93,7 +98,7 @@ func (am AccountKeeper) RemoveAccount(ctx sdk.Context, acc Account) {
// Implements sdk.AccountKeeper.
func (am AccountKeeper) IterateAccounts(ctx sdk.Context, process func(Account) (stop bool)) {
store := ctx.KVStore(am.key)
iter := sdk.KVStorePrefixIterator(store, []byte("account:"))
iter := sdk.KVStorePrefixIterator(store, AddressStoreKeyPrefix)
defer iter.Close()
for {
if !iter.Valid() {