app3 ante handler
This commit is contained in:
parent
bd581b22e8
commit
b335d3bb70
|
@ -21,13 +21,16 @@ NOTE: This documentation is a work-in-progress!
|
|||
- [Amino](core/app2.md#amino) - Amino is the primary serialization library used in the SDK
|
||||
- [Ante Handler](core/app2.md#ante-handler) - The AnteHandler
|
||||
authenticates transactions
|
||||
- [App3 - Modules](core/app3.md)
|
||||
- [Accounts](core/app3.md#accounts) - Accounts are the prototypical object kept in the store
|
||||
provides Account lookup on a KVStore
|
||||
- [Transactions](core/app3.md#transactions) - `StdTx` is the default
|
||||
implementation of `Tx`
|
||||
- [CoinKeeper](core/app3.md#coin-keeper) - CoinKeeper allows for coin
|
||||
transfer on an underlying AccountMapper
|
||||
- [App3 - Modules: Auth and Bank](core/app3.md)
|
||||
- [auth.Account](core/app3.md#accounts) - Accounts are the prototypical object kept in the store
|
||||
- [auth.AccountMapper](core/app3.md#account-mapper) - AccountMapper gets and sets Account on a KVStore
|
||||
- [auth.StdTx](core/app3.md#stdtx) - `StdTx` is the default implementation of `Tx`
|
||||
- [auth.StdSignBytes](core/app3.md#signing) - `StdTx` must be signed with certain
|
||||
information
|
||||
- [auth.AnteHandler](core/app3.md#ante-handler) - The `AnteHandler`
|
||||
verifies `StdTx`, manages accounts, and deducts fees
|
||||
- [bank.CoinKeeper](core/app3.md#coin-keeper) - CoinKeeper allows for coin
|
||||
transfers on an underlying AccountMapper
|
||||
- [App4 - Validator Set Changes](core/app4.md)
|
||||
- [InitChain](core/app4.md#init-chain) - Initialize the application
|
||||
state
|
||||
|
|
|
@ -33,6 +33,10 @@ In this model, an account contains:
|
|||
- Sequence to prevent transaction replays
|
||||
- Coins to carry a balance
|
||||
|
||||
Note that the `AccountNumber` is a unique number that is assigned when the account is
|
||||
created, and the `Sequence` is incremented by one every time a transaction is
|
||||
sent from the account.
|
||||
|
||||
### Account
|
||||
|
||||
The `Account` interface captures this account model with getters and setters:
|
||||
|
@ -146,7 +150,21 @@ type StdSignature struct {
|
|||
}
|
||||
```
|
||||
|
||||
And the standard form for a transaction fee is `StdFee`:
|
||||
The signature includes both an `AccountNumber` and a `Sequence`.
|
||||
The `Sequence` must match the one in the
|
||||
corresponding account when the transaction is processed, and will increment by
|
||||
one with every transaction. This prevents the same
|
||||
transaction from being replayed multiple times, resolving the insecurity that
|
||||
remains in App2.
|
||||
|
||||
The `AccountNumber` is also for replay protection - it allows accounts to be
|
||||
deleted from the store when they run out of accounts. If an account receives
|
||||
coins after it is deleted, the account will be re-created, with the Sequence
|
||||
reset to 0, but a new AccountNumber. If it weren't for the AccountNumber, the
|
||||
last sequence of transactions made by the account before it was deleted could be
|
||||
replayed!
|
||||
|
||||
Finally, the standard form for a transaction fee is `StdFee`:
|
||||
|
||||
```go
|
||||
// StdFee includes the amount of coins paid in fees and the maximum
|
||||
|
@ -158,36 +176,71 @@ type StdFee struct {
|
|||
}
|
||||
```
|
||||
|
||||
The fee must be paid by the first signer. This allows us to quickly check if the
|
||||
transaction fee can be paid, and reject the transaction if not.
|
||||
|
||||
## Signing
|
||||
|
||||
The standard bytes for signers to sign over is provided by:
|
||||
The `StdTx` supports multiple messages and multiple signers.
|
||||
To sign the transaction, each signer must collect the following information:
|
||||
|
||||
- the ChainID (TODO haven't mentioned this yet)
|
||||
- the AccountNumber and Sequence for the given signer's account (from the
|
||||
blockchain)
|
||||
- the transaction fee
|
||||
- the list of transaction messages
|
||||
- an optional memo
|
||||
|
||||
Then they can compute the transaction bytes to sign using the
|
||||
`auth.StdSignBytes` function:
|
||||
|
||||
```go
|
||||
TODO
|
||||
bytesToSign := StdSignBytes(chainID, accNum, accSequence, fee, msgs, memo)
|
||||
```
|
||||
|
||||
## AnteHandler
|
||||
|
||||
TODO
|
||||
As we saw in `App2`, we can use an `AnteHandler` to authenticate transactions
|
||||
before we handle any of their internal messages. While previously we implemented
|
||||
our own simple `AnteHandler`, the `x/auth` module provides a much more advanced
|
||||
one that uses `AccountMapper` and works with `StdTx`:
|
||||
|
||||
The list of signatures in the `StdTx` must match the result of `GetSigners()`
|
||||
for each `Msg`. The validation rules for the `StdTx` will be defined in the
|
||||
```go
|
||||
TODO: feekeeper :(
|
||||
app.SetAnteHandler(auth.NewAnteHandler(accountMapper, feeKeeper))
|
||||
```
|
||||
|
||||
Recall that the `Sequence` is expected to increment every time a
|
||||
message is signed by a given account in order to prevent "replay attacks" where
|
||||
the same message could be executed over and over again. The `AccountNumber` is
|
||||
assigned when the account is created or recreated after being emptied.
|
||||
The AnteHandler provided by `x/auth` enforces the following rules:
|
||||
|
||||
The `StdSignature` can also optionally include the public key for verifying the
|
||||
signature. The public key only needs to be included the first time a transaction
|
||||
is sent from a given account - from then on it will be stored in the `Account`
|
||||
and can be left out of transactions.
|
||||
- the memo must not be too big
|
||||
- the right number of signatures must be provided (one for each unique signer
|
||||
returned by `msg.GetSigner` for each `msg`)
|
||||
- any account signing for the first-time must include a public key in the
|
||||
StdSignature
|
||||
- the signatures must be valid when authenticated in the same order as specified
|
||||
by the messages
|
||||
|
||||
The fee is provided in a standard form as `StdFee`:
|
||||
Note that the address responsible for paying the transactions fee is the first address
|
||||
returned by msg.GetSigners() for the first `Msg`. The convenience function `FeePayer(tx Tx)` is provided
|
||||
to return this.
|
||||
Note that validating
|
||||
signatures requires checking that the correct account number and sequence was
|
||||
used by each signer, as this information is required in the `StdSignBytes`.
|
||||
|
||||
If any of the above are not satisfied, it returns an error.
|
||||
|
||||
If all of the above verifications pass, the AnteHandler makes the following
|
||||
changes to the state:
|
||||
|
||||
- increment account sequence by one for all signers
|
||||
- set the pubkey for any first-time signers
|
||||
- deduct the fee from the first signer
|
||||
|
||||
Recall that incrementing the `Sequence` prevents "replay attacks" where
|
||||
the same message could be executed over and over again.
|
||||
|
||||
The PubKey is required for signature verification, but it is only required in
|
||||
the StdSignature once. From that point on, it will be stored in the account.
|
||||
|
||||
The fee is paid by the first address returned by msg.GetSigners() for the first `Msg`.
|
||||
The convenience function `FeePayer(tx Tx) sdk.Address` is provided to return this.
|
||||
|
||||
## App3
|
||||
|
||||
|
|
Loading…
Reference in New Issue