Add state space to the modules and test

This commit is contained in:
Ethan Frey
2017-07-11 15:05:37 +02:00
parent 2a358010dd
commit 5cc7406a00
4 changed files with 169 additions and 7 deletions
+21 -5
View File
@@ -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)
}
+7
View File
@@ -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)
}
+2 -2
View File
@@ -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)
}
+139
View File
@@ -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)
}
}