Add handler and store

Notice that everything has json tags and that we check price in CheckTx,
while we run real code in DeliverTx.  Return values are meant for the client.
This commit is contained in:
Ethan Frey 2017-08-06 22:23:17 +02:00
parent 9fe2f6b365
commit 4c663d5551
3 changed files with 124 additions and 3 deletions

View File

@ -1,6 +1,91 @@
package etc
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/state"
wire "github.com/tendermint/go-wire"
)
const (
// Name of the module for registering it
Name = "etc"
// CostSet is the gas needed for the set operation
CostSet uint64 = 10
// CostRemove is the gas needed for the remove operation
CostRemove = 10
)
// Handler allows us to set and remove data
type Handler struct {
basecoin.NopInitState
basecoin.NopInitValidate
}
var _ basecoin.Handler = Handler{}
// NewHandler makes a role handler to modify data
func NewHandler() Handler {
return Handler{}
}
// Name - return name space
func (Handler) Name() string {
return Name
}
// CheckTx verifies if the transaction is properly formated
func (h Handler) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx) (res basecoin.CheckResult, err error) {
err = tx.ValidateBasic()
if err != nil {
return
}
switch tx.Unwrap().(type) {
case SetTx:
res = basecoin.NewCheck(CostSet, "")
case RemoveTx:
res = basecoin.NewCheck(CostRemove, "")
default:
err = errors.ErrUnknownTxType(tx)
}
return
}
// DeliverTx tries to create a new role.
//
// Returns an error if the role already exists
func (h Handler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx) (res basecoin.DeliverResult, err error) {
err = tx.ValidateBasic()
if err != nil {
return
}
switch t := tx.Unwrap().(type) {
case SetTx:
res, err = h.doSetTx(ctx, store, t)
case RemoveTx:
res, err = h.doRemoveTx(ctx, store, t)
default:
err = errors.ErrUnknownTxType(tx)
}
return
}
// doSetTx write to the store, overwriting any previous value
func (h Handler) doSetTx(ctx basecoin.Context, store state.SimpleDB, tx SetTx) (res basecoin.DeliverResult, err error) {
data := NewData(tx.Value, ctx.BlockHeight())
store.Set(tx.Key, wire.BinaryBytes(data))
return
}
// doRemoveTx deletes the value from the store and returns the last value
func (h Handler) doRemoveTx(ctx basecoin.Context, store state.SimpleDB, tx RemoveTx) (res basecoin.DeliverResult, err error) {
// we set res.Data so it gets returned to the client over the abci interface
res.Data = store.Get(tx.Key)
if len(res.Data) != 0 {
store.Remove(tx.Key)
}
return
}

View File

@ -1 +1,20 @@
package etc
import "github.com/tendermint/go-wire/data"
// Data is the struct we use to store in the merkle tree
type Data struct {
// SetAt is the block height this was set at
SetAt uint64 `json:"created_at"`
// Value is the data that was stored.
// data.Bytes is like []byte but json encodes as hex not base64
Value data.Bytes `json:"value"`
}
// NewData creates a new Data item
func NewData(value []byte, setAt uint64) Data {
return Data{
SetAt: setAt,
Value: value,
}
}

View File

@ -8,17 +8,16 @@ import (
// nolint
const (
TypeSet = Name + "/set"
TypeGet = Name + "/get"
TypeRemove = Name + "/remove"
ByteSet = 0xF0
ByteGet = 0xF1
ByteRemove = 0xF2
)
func init() {
basecoin.TxMapper.
RegisterImplementation(SetTx{}, TypeSet, ByteSet)
RegisterImplementation(SetTx{}, TypeSet, ByteSet).
RegisterImplementation(RemoveTx{}, TypeRemove, ByteRemove)
}
// SetTx sets a key-value pair
@ -39,3 +38,21 @@ func (t SetTx) ValidateBasic() error {
}
return nil
}
// RemoveTx deletes the value at this key, returns old value
type RemoveTx struct {
Key data.Bytes `json:"key"`
}
// Wrap - fulfills TxInner interface
func (t RemoveTx) Wrap() basecoin.Tx {
return basecoin.Tx{t}
}
// ValidateBasic makes sure it is valid
func (t RemoveTx) ValidateBasic() error {
if len(t.Key) == 0 {
return ErrMissingData()
}
return nil
}