From 4c663d5551476794fff8a1f4300f07bf26b3b079 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sun, 6 Aug 2017 22:23:17 +0200 Subject: [PATCH] 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. --- modules/etc/handler.go | 85 ++++++++++++++++++++++++++++++++++++++++++ modules/etc/store.go | 19 ++++++++++ modules/etc/tx.go | 23 ++++++++++-- 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/modules/etc/handler.go b/modules/etc/handler.go index e9c06620d..ba338d5fb 100644 --- a/modules/etc/handler.go +++ b/modules/etc/handler.go @@ -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 +} diff --git a/modules/etc/store.go b/modules/etc/store.go index 825503c2e..4ec45d251 100644 --- a/modules/etc/store.go +++ b/modules/etc/store.go @@ -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, + } +} diff --git a/modules/etc/tx.go b/modules/etc/tx.go index 80dbf4da0..cae743591 100644 --- a/modules/etc/tx.go +++ b/modules/etc/tx.go @@ -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 +}