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:
parent
9fe2f6b365
commit
4c663d5551
|
@ -1,6 +1,91 @@
|
||||||
package etc
|
package etc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/basecoin"
|
||||||
|
"github.com/tendermint/basecoin/errors"
|
||||||
|
"github.com/tendermint/basecoin/state"
|
||||||
|
wire "github.com/tendermint/go-wire"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Name of the module for registering it
|
// Name of the module for registering it
|
||||||
Name = "etc"
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,20 @@
|
||||||
package etc
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,17 +8,16 @@ import (
|
||||||
// nolint
|
// nolint
|
||||||
const (
|
const (
|
||||||
TypeSet = Name + "/set"
|
TypeSet = Name + "/set"
|
||||||
TypeGet = Name + "/get"
|
|
||||||
TypeRemove = Name + "/remove"
|
TypeRemove = Name + "/remove"
|
||||||
|
|
||||||
ByteSet = 0xF0
|
ByteSet = 0xF0
|
||||||
ByteGet = 0xF1
|
|
||||||
ByteRemove = 0xF2
|
ByteRemove = 0xF2
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
basecoin.TxMapper.
|
basecoin.TxMapper.
|
||||||
RegisterImplementation(SetTx{}, TypeSet, ByteSet)
|
RegisterImplementation(SetTx{}, TypeSet, ByteSet).
|
||||||
|
RegisterImplementation(RemoveTx{}, TypeRemove, ByteRemove)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTx sets a key-value pair
|
// SetTx sets a key-value pair
|
||||||
|
@ -39,3 +38,21 @@ func (t SetTx) ValidateBasic() error {
|
||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue