cosmos-sdk/modules/coin/handler.go

126 lines
2.7 KiB
Go
Raw Normal View History

2017-06-30 04:55:25 -07:00
package coin
import (
2017-07-03 09:58:28 -07:00
"fmt"
"github.com/tendermint/go-wire/data"
"github.com/tendermint/tmlibs/log"
2017-06-30 04:55:25 -07:00
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/types"
)
const (
NameCoin = "coin"
)
// Handler writes
2017-07-03 05:50:33 -07:00
type Handler struct {
Accountant
}
2017-06-30 04:55:25 -07:00
var _ basecoin.Handler = Handler{}
2017-07-03 05:50:33 -07:00
func NewHandler() Handler {
return Handler{
Accountant: Accountant{Prefix: []byte(NameCoin + "/")},
}
}
2017-06-30 04:55:25 -07:00
func (_ Handler) Name() string {
return NameCoin
}
// CheckTx checks if there is enough money in the account
func (h Handler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
send, err := checkTx(ctx, tx)
2017-06-30 04:55:25 -07:00
if err != nil {
return res, err
}
// now make sure there is money
for _, in := range send.Inputs {
_, err = h.CheckCoins(store, in.Address, in.Coins, in.Sequence)
if err != nil {
return res, err
}
}
2017-06-30 04:55:25 -07:00
// otherwise, we are good
return res, nil
}
// DeliverTx moves the money
func (h Handler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
send, err := checkTx(ctx, tx)
2017-06-30 04:55:25 -07:00
if err != nil {
return res, err
}
// deduct from all input accounts
for _, in := range send.Inputs {
_, err = h.ChangeCoins(store, in.Address, in.Coins.Negative(), in.Sequence)
if err != nil {
return res, err
}
}
// add to all output accounts
for _, out := range send.Outputs {
// note: sequence number is ignored when adding coins, only checked for subtracting
_, err = h.ChangeCoins(store, out.Address, out.Coins, 0)
if err != nil {
return res, err
}
}
// a-ok!
2017-06-30 04:55:25 -07:00
return basecoin.Result{}, nil
}
func (h Handler) SetOption(l log.Logger, store types.KVStore, key, value string) (log string, err error) {
2017-07-03 09:58:28 -07:00
if key == "base/account" {
var acc GenesisAccount
err = data.FromJSON([]byte(value), &acc)
if err != nil {
return "", err
}
acc.Balance.Sort()
addr, err := acc.GetAddr()
if err != nil {
return "", ErrInvalidAddress()
}
actor := basecoin.Actor{App: NameCoin, Address: addr}
err = storeAccount(store, h.makeKey(actor), acc.ToAccount())
if err != nil {
return "", err
}
return "Success", nil
} else {
msg := fmt.Sprintf("Unknown key: %s", key)
return "", errors.ErrInternal(msg)
}
}
2017-06-30 11:26:17 -07:00
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (send SendTx, err error) {
2017-06-30 04:55:25 -07:00
// check if the tx is proper type and valid
2017-06-30 11:26:17 -07:00
send, ok := tx.Unwrap().(SendTx)
2017-06-30 04:55:25 -07:00
if !ok {
2017-07-03 05:50:33 -07:00
return send, errors.ErrInvalidFormat(tx)
2017-06-30 04:55:25 -07:00
}
2017-06-30 11:26:17 -07:00
err = send.ValidateBasic()
2017-06-30 04:55:25 -07:00
if err != nil {
2017-06-30 11:26:17 -07:00
return send, err
2017-06-30 04:55:25 -07:00
}
// check if all inputs have permission
for _, in := range send.Inputs {
if !ctx.HasPermission(in.Address) {
2017-07-03 05:50:33 -07:00
return send, errors.ErrUnauthorized()
2017-06-30 04:55:25 -07:00
}
}
return send, nil
}