Add state space to the modules and test
This commit is contained in:
+21
-5
@@ -69,8 +69,14 @@ func (d *Dispatcher) CheckTx(ctx basecoin.Context, store state.KVStore, tx basec
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// TODO: check on callback
|
||||
cb := d
|
||||
|
||||
// make sure no monkey business with the context
|
||||
cb := secureCheck(d, ctx)
|
||||
|
||||
// and isolate the permissions and the data store for this app
|
||||
ctx = withApp(ctx, r.Name())
|
||||
store = stateSpace(store, r.Name())
|
||||
|
||||
return r.CheckTx(ctx, store, tx, cb)
|
||||
}
|
||||
|
||||
@@ -84,8 +90,14 @@ func (d *Dispatcher) DeliverTx(ctx basecoin.Context, store state.KVStore, tx bas
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// TODO: check on callback
|
||||
cb := d
|
||||
|
||||
// make sure no monkey business with the context
|
||||
cb := secureDeliver(d, ctx)
|
||||
|
||||
// and isolate the permissions and the data store for this app
|
||||
ctx = withApp(ctx, r.Name())
|
||||
store = stateSpace(store, r.Name())
|
||||
|
||||
return r.DeliverTx(ctx, store, tx, cb)
|
||||
}
|
||||
|
||||
@@ -98,8 +110,12 @@ func (d *Dispatcher) SetOption(l log.Logger, store state.KVStore, module, key, v
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// TODO: check on callback
|
||||
|
||||
// no ctx, so secureCheck not needed
|
||||
cb := d
|
||||
// but isolate data space
|
||||
store = stateSpace(store, r.Name())
|
||||
|
||||
return r.SetOption(l, store, module, key, value, cb)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ func (m *middleware) CheckTx(ctx basecoin.Context, store state.KVStore, tx basec
|
||||
next := secureCheck(m.next, ctx)
|
||||
// set the permissions for this app
|
||||
ctx = withApp(ctx, m.Name())
|
||||
store = stateSpace(store, m.Name())
|
||||
|
||||
return m.middleware.CheckTx(ctx, store, tx, next)
|
||||
}
|
||||
|
||||
@@ -36,10 +38,15 @@ func (m *middleware) DeliverTx(ctx basecoin.Context, store state.KVStore, tx bas
|
||||
next := secureDeliver(m.next, ctx)
|
||||
// set the permissions for this app
|
||||
ctx = withApp(ctx, m.Name())
|
||||
store = stateSpace(store, m.Name())
|
||||
|
||||
return m.middleware.DeliverTx(ctx, store, tx, next)
|
||||
}
|
||||
|
||||
func (m *middleware) SetOption(l log.Logger, store state.KVStore, module, key, value string) (string, error) {
|
||||
// set the namespace for the app
|
||||
store = stateSpace(store, m.Name())
|
||||
|
||||
return m.middleware.SetOption(l, store, module, key, value, m.next)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ type prefixStore struct {
|
||||
var _ state.KVStore = prefixStore{}
|
||||
|
||||
func (p prefixStore) Set(key, value []byte) {
|
||||
key = append(key, p.prefix...)
|
||||
key = append(p.prefix, key...)
|
||||
p.store.Set(key, value)
|
||||
}
|
||||
|
||||
func (p prefixStore) Get(key []byte) (value []byte) {
|
||||
key = append(key, p.prefix...)
|
||||
key = append(p.prefix, key...)
|
||||
return p.store.Get(key)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package stack
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/go-wire/data"
|
||||
)
|
||||
|
||||
// writerMid is a middleware that writes the given bytes on CheckTx and DeliverTx
|
||||
type writerMid struct {
|
||||
name string
|
||||
key, value []byte
|
||||
}
|
||||
|
||||
var _ Middleware = writerMid{}
|
||||
|
||||
func (w writerMid) Name() string { return w.name }
|
||||
|
||||
func (w writerMid) CheckTx(ctx basecoin.Context, store state.KVStore,
|
||||
tx basecoin.Tx, next basecoin.Checker) (basecoin.Result, error) {
|
||||
store.Set(w.key, w.value)
|
||||
return next.CheckTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
func (w writerMid) DeliverTx(ctx basecoin.Context, store state.KVStore,
|
||||
tx basecoin.Tx, next basecoin.Deliver) (basecoin.Result, error) {
|
||||
store.Set(w.key, w.value)
|
||||
return next.DeliverTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
func (w writerMid) SetOption(l log.Logger, store state.KVStore, module,
|
||||
key, value string, next basecoin.SetOptioner) (string, error) {
|
||||
store.Set([]byte(key), []byte(value))
|
||||
return next.SetOption(l, store, module, key, value)
|
||||
}
|
||||
|
||||
// writerHand is a middleware that writes the given bytes on CheckTx and DeliverTx
|
||||
type writerHand struct {
|
||||
name string
|
||||
key, value []byte
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = writerHand{}
|
||||
|
||||
func (w writerHand) Name() string { return w.name }
|
||||
|
||||
func (w writerHand) CheckTx(ctx basecoin.Context, store state.KVStore,
|
||||
tx basecoin.Tx) (basecoin.Result, error) {
|
||||
store.Set(w.key, w.value)
|
||||
return basecoin.Result{}, nil
|
||||
}
|
||||
|
||||
func (w writerHand) DeliverTx(ctx basecoin.Context, store state.KVStore,
|
||||
tx basecoin.Tx) (basecoin.Result, error) {
|
||||
store.Set(w.key, w.value)
|
||||
return basecoin.Result{}, nil
|
||||
}
|
||||
|
||||
func (w writerHand) SetOption(l log.Logger, store state.KVStore, module,
|
||||
key, value string) (string, error) {
|
||||
store.Set([]byte(key), []byte(value))
|
||||
return "Success", nil
|
||||
}
|
||||
|
||||
func TestStateSpace(t *testing.T) {
|
||||
cases := []struct {
|
||||
h basecoin.Handler
|
||||
m []Middleware
|
||||
expected []data.Bytes
|
||||
}{
|
||||
{
|
||||
writerHand{"foo", []byte{1, 2}, []byte("bar")},
|
||||
[]Middleware{
|
||||
writerMid{"bing", []byte{1, 2}, []byte("bang")},
|
||||
},
|
||||
[]data.Bytes{
|
||||
{'f', 'o', 'o', 0, 1, 2},
|
||||
{'b', 'i', 'n', 'g', 0, 1, 2},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
// make an app with this setup
|
||||
d := NewDispatcher(WrapHandler(tc.h))
|
||||
app := New(tc.m...).Use(d)
|
||||
|
||||
// register so RawTx is routed to this handler
|
||||
basecoin.TxMapper.RegisterImplementation(RawTx{}, tc.h.Name(), byte(50+i))
|
||||
|
||||
// run various tests on this setup
|
||||
spaceCheck(t, i, app, tc.expected)
|
||||
spaceDeliver(t, i, app, tc.expected)
|
||||
// spaceOption(t, i, app, keys)
|
||||
}
|
||||
}
|
||||
|
||||
func spaceCheck(t *testing.T, i int, app basecoin.Handler, keys []data.Bytes) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
ctx := MockContext("chain", 100)
|
||||
store := state.NewMemKVStore()
|
||||
|
||||
// run a tx
|
||||
_, err := app.CheckTx(ctx, store, NewRawTx([]byte{77}))
|
||||
require.Nil(err, "%d: %+v", i, err)
|
||||
|
||||
// verify that the data was writen
|
||||
for j, k := range keys {
|
||||
v := store.Get(k)
|
||||
assert.NotEmpty(v, "%d / %d", i, j)
|
||||
}
|
||||
}
|
||||
|
||||
func spaceDeliver(t *testing.T, i int, app basecoin.Handler, keys []data.Bytes) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
ctx := MockContext("chain", 100)
|
||||
store := state.NewMemKVStore()
|
||||
|
||||
// run a tx
|
||||
_, err := app.DeliverTx(ctx, store, NewRawTx([]byte{1, 56}))
|
||||
require.Nil(err, "%d: %+v", i, err)
|
||||
|
||||
// verify that the data was writen
|
||||
for j, k := range keys {
|
||||
v := store.Get(k)
|
||||
assert.NotEmpty(v, "%d / %d", i, j)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user