Add height to context, cleanup, add to app and stack

This commit is contained in:
Ethan Frey 2017-07-10 12:19:42 +02:00
parent 100d88d7dd
commit b6197a1c12
12 changed files with 72 additions and 84 deletions

View File

@ -31,6 +31,7 @@ type Basecoin struct {
state *sm.State
cacheState *sm.State
handler basecoin.Handler
height uint64
logger log.Logger
}
@ -45,6 +46,7 @@ func NewBasecoin(handler basecoin.Handler, eyesCli *eyes.Client, logger log.Logg
eyesCli: eyesCli,
state: state,
cacheState: nil,
height: 0,
logger: logger,
}
}
@ -73,6 +75,7 @@ func (app *Basecoin) Info() abci.ResponseInfo {
if err != nil {
cmn.PanicCrisis(err)
}
app.height = resp.LastBlockHeight
return abci.ResponseInfo{
Data: fmt.Sprintf("Basecoin v%v", version.Version),
LastBlockHeight: resp.LastBlockHeight,
@ -111,6 +114,7 @@ func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result {
cache := app.state.CacheWrap()
ctx := stack.NewContext(
app.state.GetChainID(),
app.height,
app.logger.With("call", "delivertx"),
)
res, err := app.handler.DeliverTx(ctx, cache, tx)
@ -134,6 +138,7 @@ func (app *Basecoin) CheckTx(txBytes []byte) abci.Result {
// TODO: can we abstract this setup and commit logic??
ctx := stack.NewContext(
app.state.GetChainID(),
app.height,
app.logger.With("call", "checktx"),
)
// checktx generally shouldn't touch the state, but we don't care
@ -187,6 +192,7 @@ func (app *Basecoin) InitChain(validators []*abci.Validator) {
// BeginBlock - ABCI
func (app *Basecoin) BeginBlock(hash []byte, header *abci.Header) {
app.height++
// for _, plugin := range app.plugins.GetList() {
// plugin.BeginBlock(app.state, hash, header)
// }

View File

@ -36,4 +36,5 @@ type Context interface {
IsParent(ctx Context) bool
Reset() Context
ChainID() string
BlockHeight() uint64
}

View File

@ -40,7 +40,7 @@ func BenchmarkCheckOneSig(b *testing.B) {
h := makeHandler()
store := state.NewMemKVStore()
for i := 1; i <= b.N; i++ {
ctx := stack.NewContext("foo", log.NewNopLogger())
ctx := stack.NewContext("foo", 100, log.NewNopLogger())
_, err := h.DeliverTx(ctx, store, tx)
// never should error
if err != nil {
@ -64,7 +64,7 @@ func benchmarkCheckMultiSig(b *testing.B, cnt int) {
h := makeHandler()
store := state.NewMemKVStore()
for i := 1; i <= b.N; i++ {
ctx := stack.NewContext("foo", log.NewNopLogger())
ctx := stack.NewContext("foo", 100, log.NewNopLogger())
_, err := h.DeliverTx(ctx, store, tx)
// never should error
if err != nil {

View File

@ -18,7 +18,7 @@ func TestSignatureChecks(t *testing.T) {
assert := assert.New(t)
// generic args
ctx := stack.NewContext("test-chain", log.NewNopLogger())
ctx := stack.NewContext("test-chain", 100, log.NewNopLogger())
store := state.NewMemKVStore()
raw := stack.NewRawTx([]byte{1, 2, 3, 4})

View File

@ -61,7 +61,7 @@ func TestChain(t *testing.T) {
}
// generic args here...
ctx := stack.NewContext(chainID, log.NewNopLogger())
ctx := stack.NewContext(chainID, 100, log.NewNopLogger())
store := state.NewMemKVStore()
// build the stack

View File

@ -34,7 +34,7 @@ func BenchmarkSimpleTransfer(b *testing.B) {
// now, loop...
for i := 1; i <= b.N; i++ {
ctx := stack.MockContext("foo").WithPermissions(sender)
ctx := stack.MockContext("foo", 100).WithPermissions(sender)
tx := makeSimpleTx(sender, receiver, Coins{{"mycoin", 2}}, i)
_, err := h.DeliverTx(ctx, store, tx)
// never should error

View File

@ -74,7 +74,7 @@ func TestHandlerValidation(t *testing.T) {
}
for i, tc := range cases {
ctx := stack.MockContext("base-chain").WithPermissions(tc.perms...)
ctx := stack.MockContext("base-chain", 100).WithPermissions(tc.perms...)
_, err := checkTx(ctx, tc.tx)
if tc.valid {
assert.Nil(err, "%d: %+v", i, err)
@ -148,7 +148,7 @@ func TestDeliverTx(t *testing.T) {
require.Nil(err, "%d: %+v", i, err)
}
ctx := stack.MockContext("base-chain").WithPermissions(tc.perms...)
ctx := stack.MockContext("base-chain", 100).WithPermissions(tc.perms...)
_, err := h.DeliverTx(ctx, store, tc.tx)
if len(tc.final) > 0 { // valid
assert.Nil(err, "%d: %+v", i, err)

View File

@ -1,9 +1,6 @@
package stack
import (
"bytes"
"math/rand"
"github.com/pkg/errors"
"github.com/tendermint/tmlibs/log"
@ -16,28 +13,20 @@ import (
type nonce int64
type secureContext struct {
id nonce
chain string
app string
perms []basecoin.Actor
log.Logger
app string
// this exposes the log.Logger and all other methods we don't override
naiveContext
}
// NewContext - create a new secureContext
func NewContext(chain string, logger log.Logger) basecoin.Context {
func NewContext(chain string, height uint64, logger log.Logger) basecoin.Context {
return secureContext{
id: nonce(rand.Int63()),
chain: chain,
Logger: logger,
naiveContext: MockContext(chain, height).(naiveContext),
}
}
var _ basecoin.Context = secureContext{}
func (c secureContext) ChainID() string {
return c.chain
}
// WithPermissions will panic if they try to set permission without the proper app
func (c secureContext) WithPermissions(perms ...basecoin.Actor) basecoin.Context {
// the guard makes sure you only set permissions for the app you are inside
@ -50,32 +39,18 @@ func (c secureContext) WithPermissions(perms ...basecoin.Actor) basecoin.Context
}
return secureContext{
id: c.id,
chain: c.chain,
app: c.app,
perms: append(c.perms, perms...),
Logger: c.Logger,
app: c.app,
naiveContext: c.naiveContext.WithPermissions(perms...).(naiveContext),
}
}
func (c secureContext) HasPermission(perm basecoin.Actor) bool {
for _, p := range c.perms {
if perm.App == p.App && bytes.Equal(perm.Address, p.Address) {
return true
}
// Reset should clear out all permissions,
// but carry on knowledge that this is a child
func (c secureContext) Reset() basecoin.Context {
return secureContext{
app: c.app,
naiveContext: c.naiveContext.Reset().(naiveContext),
}
return false
}
func (c secureContext) GetPermissions(chain, app string) (res []basecoin.Actor) {
for _, p := range c.perms {
if chain == p.ChainID {
if app == "" || app == p.App {
res = append(res, p)
}
}
}
return res
}
// IsParent ensures that this is derived from the given secureClient
@ -84,19 +59,7 @@ func (c secureContext) IsParent(other basecoin.Context) bool {
if !ok {
return false
}
return c.id == so.id
}
// Reset should clear out all permissions,
// but carry on knowledge that this is a child
func (c secureContext) Reset() basecoin.Context {
return secureContext{
id: c.id,
chain: c.chain,
app: c.app,
perms: nil,
Logger: c.Logger,
}
return c.naiveContext.IsParent(so.naiveContext)
}
// withApp is a private method that we can use to properly set the
@ -107,11 +70,8 @@ func withApp(ctx basecoin.Context, app string) basecoin.Context {
return ctx
}
return secureContext{
id: sc.id,
chain: sc.chain,
app: app,
perms: sc.perms,
Logger: sc.Logger,
app: app,
naiveContext: sc.naiveContext,
}
}

View File

@ -15,7 +15,7 @@ import (
func TestOK(t *testing.T) {
assert := assert.New(t)
ctx := NewContext("test-chain", log.NewNopLogger())
ctx := NewContext("test-chain", 20, log.NewNopLogger())
store := state.NewMemKVStore()
data := "this looks okay"
tx := basecoin.Tx{}
@ -33,7 +33,7 @@ func TestOK(t *testing.T) {
func TestFail(t *testing.T) {
assert := assert.New(t)
ctx := NewContext("test-chain", log.NewNopLogger())
ctx := NewContext("test-chain", 20, log.NewNopLogger())
store := state.NewMemKVStore()
msg := "big problem"
tx := basecoin.Tx{}
@ -53,7 +53,7 @@ func TestFail(t *testing.T) {
func TestPanic(t *testing.T) {
assert := assert.New(t)
ctx := NewContext("test-chain", log.NewNopLogger())
ctx := NewContext("test-chain", 20, log.NewNopLogger())
store := state.NewMemKVStore()
msg := "system crash!"
tx := basecoin.Tx{}

View File

@ -22,7 +22,7 @@ func TestPermissionSandbox(t *testing.T) {
require := require.New(t)
// generic args
ctx := NewContext("test-chain", log.NewNopLogger())
ctx := NewContext("test-chain", 20, log.NewNopLogger())
store := state.NewMemKVStore()
raw := NewRawTx([]byte{1, 2, 3, 4})
rawBytes, err := data.ToWire(raw)

View File

@ -2,40 +2,55 @@ package stack
import (
"bytes"
"math/rand"
"github.com/tendermint/tmlibs/log"
"github.com/tendermint/basecoin"
)
type mockContext struct {
perms []basecoin.Actor
chain string
type naiveContext struct {
id nonce
chain string
height uint64
perms []basecoin.Actor
log.Logger
}
func MockContext(chain string) basecoin.Context {
return mockContext{
// MockContext returns a simple, non-checking context for test cases.
//
// Always use NewContext() for production code to sandbox malicious code better
func MockContext(chain string, height uint64) basecoin.Context {
return naiveContext{
id: nonce(rand.Int63()),
chain: chain,
height: height,
Logger: log.NewNopLogger(),
}
}
var _ basecoin.Context = mockContext{}
var _ basecoin.Context = naiveContext{}
func (c mockContext) ChainID() string {
func (c naiveContext) ChainID() string {
return c.chain
}
func (c naiveContext) BlockHeight() uint64 {
return c.height
}
// WithPermissions will panic if they try to set permission without the proper app
func (c mockContext) WithPermissions(perms ...basecoin.Actor) basecoin.Context {
return mockContext{
func (c naiveContext) WithPermissions(perms ...basecoin.Actor) basecoin.Context {
return naiveContext{
id: c.id,
chain: c.chain,
height: c.height,
perms: append(c.perms, perms...),
Logger: c.Logger,
}
}
func (c mockContext) HasPermission(perm basecoin.Actor) bool {
func (c naiveContext) HasPermission(perm basecoin.Actor) bool {
for _, p := range c.perms {
if perm.App == p.App && bytes.Equal(perm.Address, p.Address) {
return true
@ -44,7 +59,7 @@ func (c mockContext) HasPermission(perm basecoin.Actor) bool {
return false
}
func (c mockContext) GetPermissions(chain, app string) (res []basecoin.Actor) {
func (c naiveContext) GetPermissions(chain, app string) (res []basecoin.Actor) {
for _, p := range c.perms {
if chain == p.ChainID {
if app == "" || app == p.App {
@ -56,15 +71,21 @@ func (c mockContext) GetPermissions(chain, app string) (res []basecoin.Actor) {
}
// IsParent ensures that this is derived from the given secureClient
func (c mockContext) IsParent(other basecoin.Context) bool {
_, ok := other.(mockContext)
return ok
func (c naiveContext) IsParent(other basecoin.Context) bool {
nc, ok := other.(naiveContext)
if !ok {
return false
}
return c.id == nc.id
}
// Reset should clear out all permissions,
// but carry on knowledge that this is a child
func (c mockContext) Reset() basecoin.Context {
return mockContext{
func (c naiveContext) Reset() basecoin.Context {
return naiveContext{
id: c.id,
chain: c.chain,
height: c.height,
Logger: c.Logger,
}
}

View File

@ -17,7 +17,7 @@ func TestRecovery(t *testing.T) {
assert := assert.New(t)
// generic args here...
ctx := NewContext("test-chain", log.NewNopLogger())
ctx := NewContext("test-chain", 20, log.NewNopLogger())
store := state.NewMemKVStore()
tx := basecoin.Tx{}