Start on coin handler

This commit is contained in:
Ethan Frey 2017-06-30 13:55:25 +02:00
parent a0f1e5e66a
commit 37796002ae
4 changed files with 96 additions and 3 deletions

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
abci "github.com/tendermint/abci/types" abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin"
) )
const ( const (
@ -26,8 +27,14 @@ const (
msgTooManySignatures = "Too many signatures" msgTooManySignatures = "Too many signatures"
msgNoChain = "No chain id provided" msgNoChain = "No chain id provided"
msgWrongChain = "Tx belongs to different chain - %s" msgWrongChain = "Tx belongs to different chain - %s"
msgUnknownTxType = "We cannot handle this tx - %v"
) )
func UnknownTxType(tx basecoin.Tx) TMError {
msg := fmt.Sprintf(msgUnknownTxType, tx)
return New(msg, abci.CodeType_UnknownRequest)
}
func InternalError(msg string) TMError { func InternalError(msg string) TMError {
return New(msg, abci.CodeType_InternalError) return New(msg, abci.CodeType_InternalError)
} }

64
modules/coin/handler.go Normal file
View File

@ -0,0 +1,64 @@
package coin
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/types"
)
const (
NameCoin = "coin"
)
// Handler writes
type Handler struct{}
var _ basecoin.Handler = Handler{}
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) {
_, err = checkTx(ctx, tx)
if err != nil {
return res, err
}
// now make sure there is money
// 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) {
_, err = checkTx(ctx, tx)
if err != nil {
return res, err
}
// now move the money
return basecoin.Result{}, nil
}
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (*SendTx, error) {
// check if the tx is proper type and valid
send, ok := tx.Unwrap().(*SendTx)
if !ok {
return nil, errors.UnknownTxType(tx)
}
err := send.ValidateBasic()
if err != nil {
return nil, err
}
// check if all inputs have permission
for _, in := range send.Inputs {
if !ctx.HasPermission(in.Address) {
return nil, errors.Unauthorized()
}
}
return send, nil
}

View File

@ -98,15 +98,23 @@ func (tx SendTx) ValidateBasic() error {
if len(tx.Outputs) == 0 { if len(tx.Outputs) == 0 {
return errors.NoOutputs() return errors.NoOutputs()
} }
// make sure all inputs and outputs are individually valid
var totalIn, totalOut types.Coins
for _, in := range tx.Inputs { for _, in := range tx.Inputs {
if err := in.ValidateBasic(); err != nil { if err := in.ValidateBasic(); err != nil {
return err return err
} }
totalIn.Plus(in.Coins)
} }
for _, out := range tx.Outputs { for _, out := range tx.Outputs {
if err := out.ValidateBasic(); err != nil { if err := out.ValidateBasic(); err != nil {
return err return err
} }
totalOut.Plus(out.Coins)
}
// make sure inputs and outputs match
if !totalIn.IsEqual(totalOut) {
return errors.InvalidCoins()
} }
return nil return nil
} }

View File

@ -1,9 +1,13 @@
package stack package stack
import ( import (
"strings"
"github.com/tendermint/basecoin" "github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/txs" "github.com/tendermint/basecoin/txs"
"github.com/tendermint/basecoin/types" "github.com/tendermint/basecoin/types"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/go-wire/data"
) )
const ( const (
@ -45,7 +49,17 @@ func runAll(ctx basecoin.Context, store types.KVStore, txs []basecoin.Tx, next b
return combine(rs), nil return combine(rs), nil
} }
func combine(res []basecoin.Result) basecoin.Result { // combines all data bytes as a go-wire array.
// TODO: how to combine??? // joins all log messages with \n
return res[0] func combine(all []basecoin.Result) basecoin.Result {
datas := make([]data.Bytes, len(all))
logs := make([]string, len(all))
for i, r := range all {
datas[i] = r.Data
logs[i] = r.Log
}
return basecoin.Result{
Data: wire.BinaryBytes(datas),
Log: strings.Join(logs, "\n"),
}
} }