cosmos-sdk/x/auth/ante.go

104 lines
2.8 KiB
Go
Raw Normal View History

package auth
import (
2018-01-12 14:30:02 -08:00
sdk "github.com/cosmos/cosmos-sdk/types"
)
func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler {
return func(
2018-01-12 14:30:02 -08:00
ctx sdk.Context, tx sdk.Tx,
2018-01-26 05:11:01 -08:00
) (_ sdk.Context, _ sdk.Result, abort bool) {
2018-01-26 06:22:56 -08:00
// Assert that there are signatures.
2018-03-03 23:32:39 -08:00
var sigs = tx.GetSignatures()
2018-02-17 13:19:34 -08:00
if len(sigs) == 0 {
return ctx,
sdk.ErrUnauthorized("no signers").Result(),
true
}
2018-01-26 04:19:33 -08:00
2018-03-03 23:32:39 -08:00
// TODO: can tx just implement message?
msg := tx.GetMsg()
2018-01-26 06:22:56 -08:00
2018-01-26 04:19:33 -08:00
// Assert that number of signatures is correct.
2018-03-03 23:32:39 -08:00
var signerAddrs = msg.GetSigners()
2018-02-17 13:19:34 -08:00
if len(sigs) != len(signerAddrs) {
return ctx,
sdk.ErrUnauthorized("wrong number of signers").Result(),
true
}
2018-03-03 23:32:39 -08:00
// Collect accounts to set in the context
var signerAccs = make([]sdk.Account, len(signerAddrs))
2018-03-03 23:32:39 -08:00
// First sig is the fee payer.
2018-03-04 00:15:26 -08:00
// signBytes uses the sequence of the fee payer
// (ie. the first account)
payerAddr, payerSig := signerAddrs[0], sigs[0]
signBytes := sdk.StdSignBytes(ctx.ChainID(), payerSig.Sequence, msg)
// Check fee payer sig and nonce, and deduct fee.
2018-03-03 23:32:39 -08:00
// This is done first because it only
// requires fetching 1 account.
2018-03-04 00:15:26 -08:00
payerAcc, res := processSig(ctx, accountMapper, payerAddr, payerSig, signBytes)
2018-03-03 23:32:39 -08:00
if !res.IsOK() {
return ctx, res, true
}
signerAccs[0] = payerAcc
// TODO: Charge fee from payerAcc.
// TODO: accountMapper.SetAccount(ctx, payerAddr)
2018-03-03 23:32:39 -08:00
// Check sig and nonce for the rest.
for i := 1; i < len(sigs); i++ {
2018-03-04 00:15:26 -08:00
signerAddr, sig := signerAddrs[i], sigs[i]
signerAcc, res := processSig(ctx, accountMapper, signerAddr, sig, signBytes)
2018-03-03 23:32:39 -08:00
if !res.IsOK() {
return ctx, res, true
}
2018-03-03 23:32:39 -08:00
signerAccs[i] = signerAcc
}
ctx = WithSigners(ctx, signerAccs)
2018-01-12 14:30:02 -08:00
return ctx, sdk.Result{}, false // continue...
}
}
2018-03-03 23:32:39 -08:00
// verify the signature and increment the sequence.
// if the account doesn't have a pubkey, set it as well.
func processSig(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, sig sdk.StdSignature, signBytes []byte) (acc sdk.Account, res sdk.Result) {
// Get the account
acc = am.GetAccount(ctx, addr)
if acc == nil {
return nil, sdk.ErrUnrecognizedAddress(addr).Result()
}
// Check and increment sequence number.
seq := acc.GetSequence()
if seq != sig.Sequence {
return nil, sdk.ErrInvalidSequence("").Result()
}
acc.SetSequence(seq + 1)
// Check and possibly set pubkey.
pubKey := acc.GetPubKey()
if pubKey.Empty() {
pubKey = sig.PubKey
err := acc.SetPubKey(pubKey)
if err != nil {
return nil, sdk.ErrInternal("setting PubKey on signer").Result()
}
}
// TODO: should we enforce pubKey == sig.PubKey ?
// If not, ppl can send useless PubKeys after first tx
// Check sig.
if !sig.PubKey.VerifyBytes(signBytes, sig.Signature) {
2018-03-04 00:15:26 -08:00
return nil, sdk.ErrUnauthorized("signature verification failed").Result()
2018-03-03 23:32:39 -08:00
}
// Save the account.
am.SetAccount(ctx, acc)
return
}