diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..e9d9ecf84dc43dfd0188a27a760e362e1e7be8fa
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,8 @@
+.git
+.project
+run.sh
+build
+Vagrantfile
+README.md
+circle.yml
+api.md
\ No newline at end of file
diff --git a/DOCKER/Dockerfile b/DOCKER/Dockerfile
index 4ee8372fc642afc79265b507633f812221ad0f1f..d58e8f8acdc4bce80a2a8ab61089ddf9bdfb781c 100644
--- a/DOCKER/Dockerfile
+++ b/DOCKER/Dockerfile
@@ -1,5 +1,6 @@
-# Pull eris/data
-FROM eris/data
+# Pull base image.
+FROM eris/base
+MAINTAINER Eris Industries <support@erisindustries.com>
 
 # Set the env variables to non-interactive
 ENV DEBIAN_FRONTEND noninteractive
@@ -14,10 +15,51 @@ RUN apt-get update && \
     libgmp3-dev && \
   rm -rf /var/lib/apt/lists/*
 
+# install the wrapper/start script
+COPY DOCKER/start.sh /usr/local/bin/erisdb-wrapper
+
 # set the repo and install tendermint
-ENV repo /go/src/github.com/eris-ltd/eris-db
-ADD . $repo
-WORKDIR $repo
-RUN cd ./cmd/erisdb && go install
-USER eris
-ENTRYPOINT ["erisdb"]
+ENV REPO github.com/tendermint/tendermint
+ENV BRANCH permissions
+RUN mkdir --parents $GOPATH/src/$REPO
+WORKDIR $GOPATH/src/$REPO
+RUN git clone https://$REPO . && \
+  git checkout $BRANCH && \
+  make && \
+  rm ./build/barak && \
+  mv ./build/* /usr/local/bin/
+
+# set the repo and install erisdb
+ENV REPO $GOPATH/src/github.com/eris-ltd/eris-db
+COPY . $REPO
+WORKDIR $REPO
+RUN cd ./cmd/erisdb && \
+  go build && \
+  mv erisdb /usr/local/bin/ && \
+  cd ../erisdbss && \
+  go build && \
+  mv erisdbss /usr/local/bin/
+
+# set the repo and install mint-client
+ENV REPO github.com/eris-ltd/mint-client
+ENV BRANCH master
+RUN mkdir --parents $GOPATH/src/$REPO
+WORKDIR $GOPATH/src/$REPO
+RUN git clone https://$REPO . && \
+  git checkout $BRANCH && \
+  go install ./... && \
+  mv $GOPATH/bin/mint* /usr/local/bin && \
+  mv ./mint-client /usr/local/bin/
+
+# cleanup
+RUN rm -rf $GOPATH/src/*
+
+# persist data, set user
+VOLUME /home/$USER/.eris
+WORKDIR /home/$USER/.eris
+USER $USER
+RUN mkdir --parents /home/$USER/.eris/blockchains/tendermint
+ENV TMROOT /home/$USER/.eris/blockchains/tendermint
+
+# run tendermint
+CMD ["erisdb-wrapper"]
diff --git a/DOCKER/build.sh b/DOCKER/build.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0ed34a66641945e6017401b9f5419ae90bac14ec
--- /dev/null
+++ b/DOCKER/build.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+base=github.com/eris-ltd/eris-db
+repo=$GOPATH/src/$base
+branch=${ERISDB_BUILD_BRANCH:=docker}
+start=`pwd`
+
+cd $repo
+git checkout $branch
+git pull origin
+
+docker build -t eris/erisdb:0.10 -f DOCKER/Dockerfile .
+
+cd $start
\ No newline at end of file
diff --git a/DOCKER/docker_build.sh b/DOCKER/docker_build.sh
deleted file mode 100755
index c914d70bf1dedb6285a5e1d8a373fdb09223f875..0000000000000000000000000000000000000000
--- a/DOCKER/docker_build.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#! /bin/sh
-
-CUR=`pwd`
-
-if [ $CUR = "$GOPATH/src/github.com/eris-ltd/erisdb" ]; then
-
-	docker build -t eris-db -f DOCKER/Dockerfile .
-else
-	docker build -t eris-db -f Dockerfile ..
-fi
-
-
-
diff --git a/DOCKER/docker_run.sh b/DOCKER/docker_run.sh
deleted file mode 100755
index 41311b33ced0d782edebb379643408eeb3d8d0bc..0000000000000000000000000000000000000000
--- a/DOCKER/docker_run.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-# Using ~/.eris on drive.
-ERIS_PATH=$HOME/.eris
-CONTAINER="eris-db"
-RUNNING=$(docker inspect --format="{{ .State.Running }}" eris-db)
-mkdir -v -p $ERIS_PATH
-
-# Run in the terminal and attach on start.
-if [ "$RUNNING" == "true" ]; then
-  echo "Container 'eris-db' already running. Exiting."
-  exit 1
-elif [ "$RUNNING" == "false" ]; then
-  echo "Container 'eris-db' found. Starting."
-  docker start --attach=true eris-db
-else
-  echo "Container 'eris-db' not found. Creating."
-  docker run --name eris-db -v $ERIS_PATH:/home/eris/.eris -p 46656:46656 -p 46657:46657 -p 1337:1337 eris-db
-fi
diff --git a/DOCKER/start.sh b/DOCKER/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..eb3457cd61f1f041726cc8429806a8fa4117e1e3
--- /dev/null
+++ b/DOCKER/start.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+if [[ $FAST_SYNC ]]; then
+  tendermint node --fast_sync
+else
+  tendermint node
+fi
+
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index d3c54ebeb5d6d3f94b7219798f7603800dc8d421..30e3d8c3fb9a9875a8864bb99e22e3c2d68323ae 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -85,83 +85,87 @@
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/account",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/alert",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/binary",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/blockchain",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/common",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/config",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/consensus",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/db",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/events",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/logger",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/mempool",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/merkle",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/node",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/p2p",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/permission/types",
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/rpc/core",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/rpc/server",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/rpc/types",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/state",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/types",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/vm",
-			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+			"Rev": "1d61dbc86b4b9e084b28b6b52412ab0a3ceab2e6"
 		},
 		{
 			"ImportPath": "github.com/tommy351/gin-cors",
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/account/account.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/account/account.go
index 1c1492abc9f02a2aa525ce527e305c2a403b8404..99c8cba5be13fbdf665b7801d4d32180fd6efe3f 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/account/account.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/account/account.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/merkle"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 )
 
 // Signable is an interface for all signable things.
@@ -42,6 +43,8 @@ type Account struct {
 	Balance     uint64 `json:"balance"`
 	Code        []byte `json:"code"`         // VM code
 	StorageRoot []byte `json:"storage_root"` // VM storage merkle root.
+
+	Permissions *ptypes.AccountPermissions `json:"permissions"`
 }
 
 func (acc *Account) Copy() *Account {
@@ -50,7 +53,8 @@ func (acc *Account) Copy() *Account {
 }
 
 func (acc *Account) String() string {
-	return fmt.Sprintf("Account{%X:%v C:%v S:%X}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot)
+	// return fmt.Sprintf("Account{%X:%v C:%v S:%X}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot)
+	return fmt.Sprintf("Account{%X:%v C:%v S:%X P:(%s)}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot, acc.Permissions)
 }
 
 func AccountEncoder(o interface{}, w io.Writer, n *int64, err *error) {
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
index d94b01df401acfbec8f650f2667d773aa5d48a6e..43e7b2b32cb197cb5e1902ee360bf993529a764c 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
@@ -1,6 +1,7 @@
 package node
 
 import (
+	"bytes"
 	"fmt"
 	"math/rand"
 	"net"
@@ -10,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary"
 	bc "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus"
@@ -42,6 +44,7 @@ type Node struct {
 	consensusState   *consensus.ConsensusState
 	consensusReactor *consensus.ConsensusReactor
 	privValidator    *sm.PrivValidator
+	genDoc           *sm.GenesisDoc
 }
 
 func NewNode() *Node {
@@ -52,9 +55,24 @@ func NewNode() *Node {
 	// Get State
 	stateDB := dbm.GetDB("state")
 	state := sm.LoadState(stateDB)
+	var genDoc *sm.GenesisDoc
 	if state == nil {
-		state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
+		genDoc, state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
 		state.Save()
+		// write the gendoc to db
+		buf, n, err := new(bytes.Buffer), new(int64), new(error)
+		binary.WriteJSON(genDoc, buf, n, err)
+		stateDB.Set(sm.GenDocKey, buf.Bytes())
+		if *err != nil {
+			panic(Fmt("Unable to write gendoc to db: %v", err))
+		}
+	} else {
+		genDocBytes := stateDB.Get(sm.GenDocKey)
+		err := new(error)
+		binary.ReadJSON(&genDoc, genDocBytes, err)
+		if *err != nil {
+			panic(Fmt("Unable to read gendoc from db: %v", err))
+		}
 	}
 	// add the chainid to the global config
 	config.Set("chain_id", state.ChainID)
@@ -115,6 +133,7 @@ func NewNode() *Node {
 		consensusState:   consensusState,
 		consensusReactor: consensusReactor,
 		privValidator:    privValidator,
+		genDoc:           genDoc,
 	}
 }
 
@@ -184,6 +203,7 @@ func (n *Node) StartRPC() {
 	core.SetMempoolReactor(n.mempoolReactor)
 	core.SetSwitch(n.sw)
 	core.SetPrivValidator(n.privValidator)
+	core.SetGenDoc(n.genDoc)
 
 	listenAddr := config.GetString("rpc_laddr")
 	mux := http.NewServeMux()
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/connection.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/connection.go
index d6119b361836bf880d57532ee914d4939ed07eda..8e48d958919a5739f67d85b965588610e2fb3aed 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/connection.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/connection.go
@@ -11,8 +11,7 @@ import (
 	"time"
 
 	flow "github.com/eris-ltd/eris-db/Godeps/_workspace/src/code.google.com/p/mxk/go1/flowcontrol"
-	//"github.com/tendermint/log15"
-	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary" //"github.com/tendermint/log15"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 )
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go
index 3755151c0ad8b4c993159454656ef93b5fcfc216..c44974f733a1593548e26d94c5e15156a2a4b2d7 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go
@@ -4,6 +4,7 @@ import (
 	"errors"
 	"fmt"
 	"net"
+	"strconv"
 	"sync/atomic"
 	"time"
 
@@ -165,6 +166,16 @@ func (sw *Switch) AddPeerWithConnection(conn net.Conn, outbound bool) (*Peer, er
 		return nil, err
 	}
 
+	// the peerNodeInfo is not verified,
+	// so we overwrite the IP with that from the conn
+	// and if we dialed out, the port too
+	// everything else we just have to trust
+	ip, port, _ := net.SplitHostPort(conn.RemoteAddr().String())
+	peerNodeInfo.Host = ip
+	if outbound {
+		porti, _ := strconv.Atoi(port)
+		peerNodeInfo.P2PPort = uint16(porti)
+	}
 	peer := newPeer(conn, peerNodeInfo, outbound, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError)
 
 	// Add the peer to .peers
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/errors.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/errors.go
new file mode 100644
index 0000000000000000000000000000000000000000..5a170a7cce5ec71ae314d72864576d492c434e41
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/errors.go
@@ -0,0 +1,44 @@
+package types
+
+import (
+	"fmt"
+)
+
+//------------------------------------------------------------------------------------------------
+// Some errors
+
+// permission number out of bounds
+type ErrInvalidPermission PermFlag
+
+func (e ErrInvalidPermission) Error() string {
+	return fmt.Sprintf("invalid permission %d", e)
+}
+
+// unknown string for permission
+type ErrInvalidPermissionString string
+
+func (e ErrInvalidPermissionString) Error() string {
+	return fmt.Sprintf("invalid permission '%s'", e)
+}
+
+// already exists (err on add)
+type ErrPermissionExists string
+
+func (e ErrPermissionExists) Error() string {
+	return fmt.Sprintf("permission '%s' already exists", e)
+}
+
+// unknown string for snative contract
+type ErrInvalidSNativeString string
+
+func (e ErrInvalidSNativeString) Error() string {
+	return fmt.Sprintf("invalid snative contract '%s'", e)
+}
+
+// set=false. This error should be caught and the global
+// value fetched for the permission by the caller
+type ErrValueNotSet PermFlag
+
+func (e ErrValueNotSet) Error() string {
+	return fmt.Sprintf("the value for permission %d is not set", e)
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go
new file mode 100644
index 0000000000000000000000000000000000000000..c530a42e547ad4ce88cabbebd4349606420774ba
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/permissions.go
@@ -0,0 +1,290 @@
+package types
+
+import (
+	"fmt"
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
+	"reflect"
+)
+
+//------------------------------------------------------------------------------------------------
+
+var (
+	GlobalPermissionsAddress    = Zero256[:20]
+	GlobalPermissionsAddress256 = Zero256
+	DougAddress                 = append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []byte("THISISDOUG")...)
+	DougAddress256              = LeftPadWord256(DougAddress)
+)
+
+// A particular permission
+type PermFlag uint64
+
+// Base permission references are like unix (the index is already bit shifted)
+const (
+	Root           PermFlag = 1 << iota // 1
+	Send                                // 2
+	Call                                // 4
+	CreateContract                      // 8
+	CreateAccount                       // 16
+	Bond                                // 32
+	Name                                // 64
+
+	DefaultBBPB = Send | Call | CreateContract | CreateAccount | Bond | Name
+
+	// XXX: must be adjusted if base perms added/removed
+	NumBasePermissions uint     = 7
+	TopBasePermission  PermFlag = 1 << (NumBasePermissions - 1)
+	AllBasePermissions PermFlag = TopBasePermission | (TopBasePermission - 1)
+
+	AllSet PermFlag = AllBasePermissions | AllSNativePermissions
+)
+
+// should have same ordering as above
+type BasePermissionsString struct {
+	Root           bool `json:"root,omitempty"`
+	Send           bool `json:"send,omitempty"`
+	Call           bool `json:"call,omitempty"`
+	CreateContract bool `json:"create_contract,omitempty"`
+	CreateAccount  bool `json:"create_account,omitempty"`
+	Bond           bool `json:"bond,omitempty"`
+	Name           bool `json:"name,omitempty"`
+}
+
+//---------------------------------------------------------------------------------------------
+
+// Base chain permissions struct
+type BasePermissions struct {
+	// bit array with "has"/"doesn't have" for each permission
+	Perms PermFlag `json:"perms"`
+
+	// bit array with "set"/"not set" for each permission (not-set should fall back to global)
+	SetBit PermFlag `json:"set"`
+}
+
+func NewBasePermissions() *BasePermissions {
+	return &BasePermissions{0, 0}
+}
+
+// Get a permission value. ty should be a power of 2.
+// ErrValueNotSet is returned if the permission's set bit is off,
+// and should be caught by caller so the global permission can be fetched
+func (p *BasePermissions) Get(ty PermFlag) (bool, error) {
+	if ty == 0 {
+		return false, ErrInvalidPermission(ty)
+	}
+	if p.SetBit&ty == 0 {
+		return false, ErrValueNotSet(ty)
+	}
+	return p.Perms&ty > 0, nil
+}
+
+// Set a permission bit. Will set the permission's set bit to true.
+func (p *BasePermissions) Set(ty PermFlag, value bool) error {
+	if ty == 0 {
+		return ErrInvalidPermission(ty)
+	}
+	p.SetBit |= ty
+	if value {
+		p.Perms |= ty
+	} else {
+		p.Perms &= ^ty
+	}
+	return nil
+}
+
+// Set the permission's set bit to false
+func (p *BasePermissions) Unset(ty PermFlag) error {
+	if ty == 0 {
+		return ErrInvalidPermission(ty)
+	}
+	p.SetBit &= ^ty
+	return nil
+}
+
+// Check if the permission is set
+func (p *BasePermissions) IsSet(ty PermFlag) bool {
+	if ty == 0 {
+		return false
+	}
+	return p.SetBit&ty > 0
+}
+
+func (p *BasePermissions) Copy() *BasePermissions {
+	if p == nil {
+		return nil
+	}
+	return &BasePermissions{
+		Perms:  p.Perms,
+		SetBit: p.SetBit,
+	}
+}
+
+func (p *BasePermissions) String() string {
+	return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
+}
+
+//---------------------------------------------------------------------------------------------
+
+type AccountPermissions struct {
+	Base  *BasePermissions `json:"base"`
+	Roles []string         `json:"roles"`
+}
+
+func NewAccountPermissions() *AccountPermissions {
+	return &AccountPermissions{
+		Base:  NewBasePermissions(),
+		Roles: []string{},
+	}
+}
+
+// Returns true if the role is found
+func (aP *AccountPermissions) HasRole(role string) bool {
+	role = string(LeftPadBytes([]byte(role), 32))
+	for _, r := range aP.Roles {
+		if r == role {
+			return true
+		}
+	}
+	return false
+}
+
+// Returns true if the role is added, and false if it already exists
+func (aP *AccountPermissions) AddRole(role string) bool {
+	role = string(LeftPadBytes([]byte(role), 32))
+	for _, r := range aP.Roles {
+		if r == role {
+			return false
+		}
+	}
+	aP.Roles = append(aP.Roles, role)
+	return true
+}
+
+// Returns true if the role is removed, and false if it is not found
+func (aP *AccountPermissions) RmRole(role string) bool {
+	role = string(LeftPadBytes([]byte(role), 32))
+	for i, r := range aP.Roles {
+		if r == role {
+			post := []string{}
+			if len(aP.Roles) > i+1 {
+				post = aP.Roles[i+1:]
+			}
+			aP.Roles = append(aP.Roles[:i], post...)
+			return true
+		}
+	}
+	return false
+}
+
+func (aP *AccountPermissions) Copy() *AccountPermissions {
+	if aP == nil {
+		return nil
+	}
+	r := make([]string, len(aP.Roles))
+	copy(r, aP.Roles)
+	return &AccountPermissions{
+		Base:  aP.Base.Copy(),
+		Roles: r,
+	}
+}
+
+func NewDefaultAccountPermissions() *AccountPermissions {
+	return &AccountPermissions{
+		Base: &BasePermissions{
+			Perms:  DefaultBBPB,
+			SetBit: AllSet,
+		},
+		Roles: []string{},
+	}
+}
+
+//---------------------------------------------------------------------------------------------
+// Utilities to make bitmasks human readable
+
+func NewDefaultAccountPermissionsString() BasePermissionsString {
+	return BasePermissionsString{
+		Root:           false,
+		Bond:           true,
+		Send:           true,
+		Call:           true,
+		Name:           true,
+		CreateAccount:  true,
+		CreateContract: true,
+	}
+}
+
+func AccountPermissionsFromStrings(perms *BasePermissionsString, roles []string) (*AccountPermissions, error) {
+	base := NewBasePermissions()
+	permRv := reflect.ValueOf(perms)
+	for i := uint(0); i < uint(permRv.NumField()); i++ {
+		v := permRv.Field(int(i)).Bool()
+		base.Set(1<<i, v)
+	}
+
+	aP := &AccountPermissions{
+		Base:  base,
+		Roles: make([]string, len(roles)),
+	}
+	copy(aP.Roles, roles)
+	return aP, nil
+}
+
+func AccountPermissionsToStrings(aP *AccountPermissions) (*BasePermissionsString, []string, error) {
+	perms := new(BasePermissionsString)
+	permsRv := reflect.ValueOf(perms).Elem()
+	for i := uint(0); i < NumBasePermissions; i++ {
+		pf := PermFlag(1 << i)
+		if aP.Base.IsSet(pf) {
+			// won't err if the bit is set
+			v, _ := aP.Base.Get(pf)
+			f := permsRv.Field(int(i))
+			f.SetBool(v)
+		}
+	}
+	roles := make([]string, len(aP.Roles))
+	copy(roles, aP.Roles)
+	return perms, roles, nil
+}
+
+func PermFlagToString(pf PermFlag) (perm string, err error) {
+	switch pf {
+	case Root:
+		perm = "root"
+	case Send:
+		perm = "send"
+	case Call:
+		perm = "call"
+	case CreateContract:
+		perm = "create_contract"
+	case CreateAccount:
+		perm = "create_account"
+	case Bond:
+		perm = "bond"
+	case Name:
+		perm = "name"
+	default:
+		err = fmt.Errorf("Unknown permission flag %b", pf)
+	}
+	return
+}
+
+func PermStringToFlag(perm string) (pf PermFlag, err error) {
+	switch perm {
+	case "root":
+		pf = Root
+	case "send":
+		pf = Send
+	case "call":
+		pf = Call
+	case "create_contract":
+		pf = CreateContract
+	case "create_account":
+		pf = CreateAccount
+	case "bond":
+		pf = Bond
+	case "name":
+		pf = Name
+	default:
+		err = fmt.Errorf("Unknown permission %s", perm)
+	}
+	return
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/snatives.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/snatives.go
new file mode 100644
index 0000000000000000000000000000000000000000..d4e0ee4bacbd730aee06c9d4973bb7aa9fe76294
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types/snatives.go
@@ -0,0 +1,24 @@
+package types
+
+const (
+	// first 32 bits of BasePermission are for chain, second 32 are for snative
+	FirstSNativePerm PermFlag = 1 << 32
+)
+
+// we need to reset iota with no const block
+const (
+	// each snative has an associated permission flag
+	HasBasePerm PermFlag = FirstSNativePerm << iota
+	SetBasePerm
+	UnsetBasePerm
+	SetGlobalPerm
+	ClearBasePerm
+	HasRole
+	AddRole
+	RmRole
+
+	// XXX: must be adjusted if snative's added/removed
+	NumSNativePermissions uint     = 8
+	TopSNativePermission  PermFlag = FirstSNativePerm << (NumSNativePermissions - 1)
+	AllSNativePermissions PermFlag = (TopSNativePermission | (TopSNativePermission - 1)) &^ (FirstSNativePerm - 1)
+)
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/accounts.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/accounts.go
index c2c9daf0a853790bdb64de751cba30e15ef73ff1..d256242cfeda60efd629013479318582de0949ee 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/accounts.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/accounts.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 )
 
@@ -15,6 +16,7 @@ func GetAccount(address []byte) (*acm.Account, error) {
 	cache := mempoolReactor.Mempool.GetCache()
 	account := cache.GetAccount(address)
 	if account == nil {
+		// XXX: shouldn't we return "account not found"?
 		account = &acm.Account{
 			Address:     address,
 			PubKey:      nil,
@@ -22,6 +24,7 @@ func GetAccount(address []byte) (*acm.Account, error) {
 			Balance:     0,
 			Code:        nil,
 			StorageRoot: nil,
+			Permissions: cache.GetAccount(ptypes.GlobalPermissionsAddress).Permissions,
 		}
 	}
 	return account, nil
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/net.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/net.go
index 22af3e9a23d1ee1534caa017a3c603c2ba287034..715e27fdc18aeec6e73cab96f8f9e9a2c1850e0a 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/net.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/net.go
@@ -1,9 +1,6 @@
 package core
 
 import (
-	"io/ioutil"
-
-	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary"
 	dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
 	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 	sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state"
@@ -12,9 +9,14 @@ import (
 
 //-----------------------------------------------------------------------------
 
+// cache the genesis state
+var genesisState *sm.State
+
 func Status() (*ctypes.ResponseStatus, error) {
 	db := dbm.NewMemDB()
-	genesisState := sm.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
+	if genesisState == nil {
+		genesisState = sm.MakeGenesisState(db, genDoc)
+	}
 	genesisHash := genesisState.Hash()
 	latestHeight := blockStore.Height()
 	var (
@@ -63,19 +65,6 @@ func NetInfo() (*ctypes.ResponseNetInfo, error) {
 
 //-----------------------------------------------------------------------------
 
-// cache the genesis structure
-var genDoc *sm.GenesisDoc
-
 func Genesis() (*sm.GenesisDoc, error) {
-	if genDoc == nil {
-		b, err := ioutil.ReadFile(config.GetString("genesis_file"))
-		if err != nil {
-			return nil, err
-		}
-		binary.ReadJSON(&genDoc, b, &err)
-		if err != nil {
-			return nil, err
-		}
-	}
 	return genDoc, nil
 }
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/pipe.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/pipe.go
index a2c115f9d8eb0a542c945941b8137d9fea4ea659..92a50dc10a6add3620493c8a69231ce8580c79cb 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/pipe.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/pipe.go
@@ -14,6 +14,7 @@ var consensusReactor *consensus.ConsensusReactor
 var mempoolReactor *mempl.MempoolReactor
 var p2pSwitch *p2p.Switch
 var privValidator *state.PrivValidator
+var genDoc *state.GenesisDoc // cache the genesis structure
 
 func SetBlockStore(bs *bc.BlockStore) {
 	blockStore = bs
@@ -38,3 +39,7 @@ func SetSwitch(sw *p2p.Switch) {
 func SetPrivValidator(pv *state.PrivValidator) {
 	privValidator = pv
 }
+
+func SetGenDoc(doc *state.GenesisDoc) {
+	genDoc = doc
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go
index 9bf9a908d47eeedf2aeec3762d4b695f8e82b545..4205bbeafeafeb8a155162d044eb3a8bce6699d6 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go
@@ -5,15 +5,17 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
-	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary"
-	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
-	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types"
 	"io/ioutil"
 	"net/http"
 	"reflect"
+	"sort"
 	"sync/atomic"
 	"time"
+
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types"
 )
 
 func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc) {
@@ -87,6 +89,14 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc {
 			return
 		}
 		b, _ := ioutil.ReadAll(r.Body)
+
+		// if its an empty request (like from a browser),
+		// just display a list of functions
+		if len(b) == 0 {
+			writeListOfEndpoints(w, r, funcMap)
+			return
+		}
+
 		var request RPCRequest
 		err := json.Unmarshal(b, &request)
 		if err != nil {
@@ -393,3 +403,43 @@ func unreflectResponse(returns []reflect.Value) (interface{}, error) {
 	}
 	return returns[0].Interface(), nil
 }
+
+// writes a list of available rpc endpoints as an html page
+func writeListOfEndpoints(w http.ResponseWriter, r *http.Request, funcMap map[string]*RPCFunc) {
+	noArgNames := []string{}
+	argNames := []string{}
+	for name, funcData := range funcMap {
+		if len(funcData.args) == 0 {
+			noArgNames = append(noArgNames, name)
+		} else {
+			argNames = append(argNames, name)
+		}
+	}
+	sort.Strings(noArgNames)
+	sort.Strings(argNames)
+	buf := new(bytes.Buffer)
+	buf.WriteString("<html><body>")
+	buf.WriteString("<br>Available endpoints:<br>")
+
+	for _, name := range noArgNames {
+		link := fmt.Sprintf("http://%s/%s", r.Host, name)
+		buf.WriteString(fmt.Sprintf("<a href=\"%s\">%s</a></br>", link, link))
+	}
+
+	buf.WriteString("<br>Endpoints that require arguments:<br>")
+	for _, name := range argNames {
+		link := fmt.Sprintf("http://%s/%s?", r.Host, name)
+		funcData := funcMap[name]
+		for i, argName := range funcData.argNames {
+			link += argName + "=_"
+			if i < len(funcData.argNames)-1 {
+				link += "&"
+			}
+		}
+		buf.WriteString(fmt.Sprintf("<a href=\"%s\">%s</a></br>", link, link))
+	}
+	buf.WriteString("</body></html>")
+	w.Header().Set("Content-Type", "text/html")
+	w.WriteHeader(200)
+	w.Write(buf.Bytes())
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/execution.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/execution.go
index 438086dd9b1a71d707c204c3ed8d315f216447c9..e59d92b278234e66b32e8c7f381c089e44eb2211 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/execution.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/execution.go
@@ -8,6 +8,7 @@ import (
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" // for GlobalPermissionAddress ...
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm"
 )
@@ -163,7 +164,7 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
 // account.PubKey.(type) != nil, (it must be known),
 // or it must be specified in the TxInput.  If redeclared,
 // the TxInput is modified and input.PubKey set to nil.
-func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types.TxOutput) (map[string]*account.Account, error) {
+func getInputs(state AccountGetter, ins []*types.TxInput) (map[string]*account.Account, error) {
 	accounts := map[string]*account.Account{}
 	for _, in := range ins {
 		// Account shouldn't be duplicated
@@ -180,6 +181,16 @@ func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types.
 		}
 		accounts[string(in.Address)] = acc
 	}
+	return accounts, nil
+}
+
+func getOrMakeOutputs(state AccountGetter, accounts map[string]*account.Account, outs []*types.TxOutput) (map[string]*account.Account, error) {
+	if accounts == nil {
+		accounts = make(map[string]*account.Account)
+	}
+
+	// we should err if an account is being created but the inputs don't have permission
+	var checkedCreatePerms bool
 	for _, out := range outs {
 		// Account shouldn't be duplicated
 		if _, ok := accounts[string(out.Address)]; ok {
@@ -188,11 +199,18 @@ func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types.
 		acc := state.GetAccount(out.Address)
 		// output account may be nil (new)
 		if acc == nil {
+			if !checkedCreatePerms {
+				if !hasCreateAccountPermission(state, accounts) {
+					return nil, fmt.Errorf("At least one input does not have permission to create accounts")
+				}
+				checkedCreatePerms = true
+			}
 			acc = &account.Account{
-				Address:  out.Address,
-				PubKey:   nil,
-				Sequence: 0,
-				Balance:  0,
+				Address:     out.Address,
+				PubKey:      nil,
+				Sequence:    0,
+				Balance:     0,
+				Permissions: ptypes.NewAccountPermissions(),
 			}
 		}
 		accounts[string(out.Address)] = acc
@@ -293,7 +311,6 @@ func adjustByOutputs(accounts map[string]*account.Account, outs []*types.TxOutpu
 // If the tx is invalid, an error will be returned.
 // Unlike ExecBlock(), state will not be altered.
 func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Fireable) error {
-
 	// TODO: do something with fees
 	fees := uint64(0)
 	_s := blockCache.State() // hack to access validators and block height
@@ -301,10 +318,23 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 	// Exec tx
 	switch tx := tx_.(type) {
 	case *types.SendTx:
-		accounts, err := getOrMakeAccounts(blockCache, tx.Inputs, tx.Outputs)
+		accounts, err := getInputs(blockCache, tx.Inputs)
+		if err != nil {
+			return err
+		}
+
+		// ensure all inputs have send permissions
+		if !hasSendPermission(blockCache, accounts) {
+			return fmt.Errorf("At least one input lacks permission for SendTx")
+		}
+
+		// add outputs to accounts map
+		// if any outputs don't exist, all inputs must have CreateAccount perm
+		accounts, err = getOrMakeOutputs(blockCache, accounts, tx.Outputs)
 		if err != nil {
 			return err
 		}
+
 		signBytes := account.SignBytes(_s.ChainID, tx)
 		inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
 		if err != nil {
@@ -348,6 +378,18 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 			log.Debug(Fmt("Can't find in account %X", tx.Input.Address))
 			return types.ErrTxInvalidAddress
 		}
+
+		createAccount := len(tx.Address) == 0
+		if createAccount {
+			if !hasCreateContractPermission(blockCache, inAcc) {
+				return fmt.Errorf("Account %X does not have Create permission", tx.Input.Address)
+			}
+		} else {
+			if !hasCallPermission(blockCache, inAcc) {
+				return fmt.Errorf("Account %X does not have Call permission", tx.Input.Address)
+			}
+		}
+
 		// pubKey should be present in either "inAcc" or "tx.Input"
 		if err := checkInputPubKey(inAcc, tx.Input); err != nil {
 			log.Debug(Fmt("Can't find pubkey for %X", tx.Input.Address))
@@ -364,7 +406,6 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 			return types.ErrTxInsufficientFunds
 		}
 
-		createAccount := len(tx.Address) == 0
 		if !createAccount {
 			// Validate output
 			if len(tx.Address) != 20 {
@@ -374,6 +415,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 			// this may be nil if we are still in mempool and contract was created in same block as this tx
 			// but that's fine, because the account will be created properly when the create tx runs in the block
 			// and then this won't return nil. otherwise, we take their fee
+			// it may also be nil if its an snative (not a "real" account)
 			outAcc = blockCache.GetAccount(tx.Address)
 		}
 
@@ -400,26 +442,31 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 				}
 			)
 
-			// Maybe create a new callee account if
-			// this transaction is creating a new contract.
+			// get or create callee
 			if !createAccount {
+
 				if outAcc == nil || len(outAcc.Code) == 0 {
-					// if you call an account that doesn't exist
-					// or an account with no code then we take fees (sorry pal)
-					// NOTE: it's fine to create a contract and call it within one
-					// block (nonce will prevent re-ordering of those txs)
-					// but to create with one account and call with another
-					// you have to wait a block to avoid a re-ordering attack
-					// that will take your fees
-					inAcc.Balance -= tx.Fee
-					blockCache.UpdateAccount(inAcc)
-					if outAcc == nil {
-						log.Debug(Fmt("Cannot find destination address %X. Deducting fee from caller", tx.Address))
+					// check if its an snative
+					if _, ok := vm.RegisteredSNativeContracts[LeftPadWord256(tx.Address)]; ok {
+						// set the outAcc (simply a placeholder until we reach the call)
+						outAcc = &account.Account{Address: tx.Address}
 					} else {
-						log.Debug(Fmt("Attempting to call an account (%X) with no code. Deducting fee from caller", tx.Address))
+						// if you call an account that doesn't exist
+						// or an account with no code then we take fees (sorry pal)
+						// NOTE: it's fine to create a contract and call it within one
+						// block (nonce will prevent re-ordering of those txs)
+						// but to create with one account and call with another
+						// you have to wait a block to avoid a re-ordering attack
+						// that will take your fees
+						inAcc.Balance -= tx.Fee
+						blockCache.UpdateAccount(inAcc)
+						if outAcc == nil {
+							log.Debug(Fmt("Cannot find destination address %X. Deducting fee from caller", tx.Address))
+						} else {
+							log.Debug(Fmt("Attempting to call an account (%X) with no code. Deducting fee from caller", tx.Address))
+						}
+						return types.ErrTxInvalidAddress
 					}
-					return types.ErrTxInvalidAddress
-
 				}
 				callee = toVMAccount(outAcc)
 				code = callee.Code
@@ -431,12 +478,16 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 			}
 			log.Debug(Fmt("Code for this contract: %X", code))
 
-			txCache.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
-			txCache.UpdateAccount(callee) // because we adjusted by input above.
+			txCache.UpdateAccount(caller) // because we bumped nonce
+			txCache.UpdateAccount(callee) // so the txCache knows about the callee and the create and/or transfer takes effect
+
 			vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx))
 			vmach.SetFireable(evc)
-			// NOTE: Call() transfers the value from caller to callee iff call succeeds.
 
+			vmach.EnablePermissions() // permission checks on CALL/CREATE
+			vmach.EnableSNatives()    // allows calls to snatives (with permission checks)
+
+			// NOTE: Call() transfers the value from caller to callee iff call succeeds.
 			ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
 			exception := ""
 			if err != nil {
@@ -487,6 +538,10 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 			log.Debug(Fmt("Can't find in account %X", tx.Input.Address))
 			return types.ErrTxInvalidAddress
 		}
+		// check permission
+		if !hasNamePermission(blockCache, inAcc) {
+			return fmt.Errorf("Account %X does not have Name permission", tx.Input.Address)
+		}
 		// pubKey should be present in either "inAcc" or "tx.Input"
 		if err := checkInputPubKey(inAcc, tx.Input); err != nil {
 			log.Debug(Fmt("Can't find pubkey for %X", tx.Input.Address))
@@ -599,11 +654,32 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 			// add funds, merge UnbondTo outputs, and unbond validator.
 			return errors.New("Adding coins to existing validators not yet supported")
 		}
-		accounts, err := getOrMakeAccounts(blockCache, tx.Inputs, nil)
+
+		accounts, err := getInputs(blockCache, tx.Inputs)
 		if err != nil {
 			return err
 		}
 
+		// add outputs to accounts map
+		// if any outputs don't exist, all inputs must have CreateAccount perm
+		// though outputs aren't created until unbonding/release time
+		canCreate := hasCreateAccountPermission(blockCache, accounts)
+		for _, out := range tx.UnbondTo {
+			acc := blockCache.GetAccount(out.Address)
+			if acc == nil && !canCreate {
+				return fmt.Errorf("At least one input does not have permission to create accounts")
+			}
+		}
+
+		bondAcc := blockCache.GetAccount(tx.PubKey.Address())
+		if !hasBondPermission(blockCache, bondAcc) {
+			return fmt.Errorf("The bonder does not have permission to bond")
+		}
+
+		if !hasBondOrSendPermission(blockCache, accounts) {
+			return fmt.Errorf("At least one input lacks permission to bond")
+		}
+
 		signBytes := account.SignBytes(_s.ChainID, tx)
 		inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
 		if err != nil {
@@ -754,3 +830,73 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
 		panic("Unknown Tx type")
 	}
 }
+
+//---------------------------------------------------------------
+
+// Get permission on an account or fall back to global value
+func HasPermission(state AccountGetter, acc *account.Account, perm ptypes.PermFlag) bool {
+	if perm > ptypes.AllBasePermissions {
+		panic("Checking an unknown permission in state should never happen")
+	}
+
+	if acc == nil {
+		// TODO
+		// this needs to fall back to global or do some other specific things
+		// eg. a bondAcc may be nil and so can only bond if global bonding is true
+	}
+
+	v, err := acc.Permissions.Base.Get(perm)
+	if _, ok := err.(ptypes.ErrValueNotSet); ok {
+		if state == nil {
+			panic("All known global permissions should be set!")
+		}
+		return HasPermission(nil, state.GetAccount(ptypes.GlobalPermissionsAddress), perm)
+	}
+	return v
+}
+
+// TODO: for debug log the failed accounts
+func hasSendPermission(state AccountGetter, accs map[string]*account.Account) bool {
+	for _, acc := range accs {
+		if !HasPermission(state, acc, ptypes.Send) {
+			return false
+		}
+	}
+	return true
+}
+
+func hasNamePermission(state AccountGetter, acc *account.Account) bool {
+	return HasPermission(state, acc, ptypes.Name)
+}
+
+func hasCallPermission(state AccountGetter, acc *account.Account) bool {
+	return HasPermission(state, acc, ptypes.Call)
+}
+
+func hasCreateContractPermission(state AccountGetter, acc *account.Account) bool {
+	return HasPermission(state, acc, ptypes.CreateContract)
+}
+
+func hasCreateAccountPermission(state AccountGetter, accs map[string]*account.Account) bool {
+	for _, acc := range accs {
+		if !HasPermission(state, acc, ptypes.CreateAccount) {
+			return false
+		}
+	}
+	return true
+}
+
+func hasBondPermission(state AccountGetter, acc *account.Account) bool {
+	return HasPermission(state, acc, ptypes.Bond)
+}
+
+func hasBondOrSendPermission(state AccountGetter, accs map[string]*account.Account) bool {
+	for _, acc := range accs {
+		if !HasPermission(state, acc, ptypes.Bond) {
+			if !HasPermission(state, acc, ptypes.Send) {
+				return false
+			}
+		}
+	}
+	return true
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis.go
index fcb51f081375b5f7e74a63f2aa8aae6f66590f3e..2fda4ba0766ba25efe7de282037db6db5b2f1857 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis.go
@@ -9,27 +9,52 @@ import (
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/merkle"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 )
 
-type GenesisAccount struct {
+//------------------------------------------------------------
+// we store the gendoc in the db
+
+var GenDocKey = []byte("GenDocKey")
+
+//------------------------------------------------------------
+// core types for a genesis definition
+
+type BasicAccount struct {
 	Address []byte `json:"address"`
 	Amount  uint64 `json:"amount"`
 }
 
+type GenesisAccount struct {
+	Address     []byte                     `json:"address"`
+	Amount      uint64                     `json:"amount"`
+	Name        string                     `json:"name"`
+	Permissions *ptypes.AccountPermissions `json:"permissions"`
+}
+
 type GenesisValidator struct {
 	PubKey   account.PubKeyEd25519 `json:"pub_key"`
 	Amount   uint64                `json:"amount"`
-	UnbondTo []GenesisAccount      `json:"unbond_to"`
+	Name     string                `json:"name"`
+	UnbondTo []BasicAccount        `json:"unbond_to"`
+}
+
+type GenesisParams struct {
+	GlobalPermissions *ptypes.AccountPermissions `json:"global_permissions"`
 }
 
 type GenesisDoc struct {
 	GenesisTime time.Time          `json:"genesis_time"`
 	ChainID     string             `json:"chain_id"`
+	Params      *GenesisParams     `json:"params"`
 	Accounts    []GenesisAccount   `json:"accounts"`
 	Validators  []GenesisValidator `json:"validators"`
 }
 
+//------------------------------------------------------------
+// Make genesis state from file
+
 func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
 	var err error
 	binary.ReadJSON(&genState, jsonBlob, &err)
@@ -39,13 +64,13 @@ func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
 	return
 }
 
-func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
+func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*GenesisDoc, *State) {
 	jsonBlob, err := ioutil.ReadFile(genDocFile)
 	if err != nil {
 		panic(Fmt("Couldn't read GenesisDoc file: %v", err))
 	}
 	genDoc := GenesisDocFromJSON(jsonBlob)
-	return MakeGenesisState(db, genDoc)
+	return genDoc, MakeGenesisState(db, genDoc)
 }
 
 func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
@@ -60,15 +85,39 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
 	// Make accounts state tree
 	accounts := merkle.NewIAVLTree(binary.BasicCodec, account.AccountCodec, defaultAccountsCacheCapacity, db)
 	for _, genAcc := range genDoc.Accounts {
+		perm := ptypes.NewDefaultAccountPermissions()
+		if genAcc.Permissions != nil {
+			perm = genAcc.Permissions
+		}
 		acc := &account.Account{
-			Address:  genAcc.Address,
-			PubKey:   nil,
-			Sequence: 0,
-			Balance:  genAcc.Amount,
+			Address:     genAcc.Address,
+			PubKey:      nil,
+			Sequence:    0,
+			Balance:     genAcc.Amount,
+			Permissions: perm,
 		}
 		accounts.Set(acc.Address, acc)
 	}
 
+	// global permissions are saved as the 0 address
+	// so they are included in the accounts tree
+	globalPerms := ptypes.NewDefaultAccountPermissions()
+	if genDoc.Params != nil && genDoc.Params.GlobalPermissions != nil {
+		globalPerms = genDoc.Params.GlobalPermissions
+		// XXX: make sure the set bits are all true
+		// Without it the HasPermission() functions will fail
+		globalPerms.Base.SetBit = ptypes.AllSet
+	}
+
+	permsAcc := &account.Account{
+		Address:     ptypes.GlobalPermissionsAddress,
+		PubKey:      nil,
+		Sequence:    0,
+		Balance:     1337,
+		Permissions: globalPerms,
+	}
+	accounts.Set(permsAcc.Address, permsAcc)
+
 	// Make validatorInfos state tree && validators slice
 	validatorInfos := merkle.NewIAVLTree(binary.BasicCodec, ValidatorInfoCodec, 0, db)
 	validators := make([]*Validator, len(genDoc.Validators))
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..eadd1738c6efbdd6191458f6419ac3c6e03b8c48
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/genesis_test.go
@@ -0,0 +1,86 @@
+package state
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"testing"
+
+	tdb "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
+)
+
+var chain_id = "lone_ranger"
+var addr1, _ = hex.DecodeString("964B1493BBE3312278B7DEB94C39149F7899A345")
+var send1, name1, call1 = 1, 1, 0
+var perms, setbit = 66, 70
+var accName = "me"
+var roles1 = []string{"master", "universal-ruler"}
+var amt1 uint64 = 1000000
+var g1 = fmt.Sprintf(`
+{
+    "chain_id":"%s",
+    "accounts": [
+        {
+            "address": "%X",
+            "amount": %d,
+	    "name": "%s",
+            "permissions": {
+		    "base": {
+			    "perms": %d,
+			    "set": %d
+		    },
+            	    "roles": [
+			"%s",
+			"%s"
+            	]
+	    }
+        }
+    ],
+    "validators": [
+        {
+            "amount": 100000000,
+            "pub_key": [1,"F6C79CF0CB9D66B677988BCB9B8EADD9A091CD465A60542A8AB85476256DBA92"],
+            "unbond_to": [
+                {
+                    "address": "964B1493BBE3312278B7DEB94C39149F7899A345",
+                    "amount": 10000000
+                }
+            ]
+        }
+    ]
+}
+`, chain_id, addr1, amt1, accName, perms, setbit, roles1[0], roles1[1])
+
+func TestGenesisReadable(t *testing.T) {
+	genDoc := GenesisDocFromJSON([]byte(g1))
+	if genDoc.ChainID != chain_id {
+		t.Fatalf("Incorrect chain id. Got %d, expected %d\n", genDoc.ChainID, chain_id)
+	}
+	acc := genDoc.Accounts[0]
+	if bytes.Compare(acc.Address, addr1) != 0 {
+		t.Fatalf("Incorrect address for account. Got %X, expected %X\n", acc.Address, addr1)
+	}
+	if acc.Amount != amt1 {
+		t.Fatalf("Incorrect amount for account. Got %d, expected %d\n", acc.Amount, amt1)
+	}
+	if acc.Name != accName {
+		t.Fatalf("Incorrect name for account. Got %s, expected %s\n", acc.Name, accName)
+	}
+
+	perm, _ := acc.Permissions.Base.Get(ptypes.Send)
+	if perm != (send1 > 0) {
+		t.Fatalf("Incorrect permission for send. Got %v, expected %v\n", perm, send1 > 0)
+	}
+}
+
+func TestGenesisMakeState(t *testing.T) {
+	genDoc := GenesisDocFromJSON([]byte(g1))
+	db := tdb.NewMemDB()
+	st := MakeGenesisState(db, genDoc)
+	acc := st.GetAccount(addr1)
+	v, _ := acc.Permissions.Base.Get(ptypes.Send)
+	if v != (send1 > 0) {
+		t.Fatalf("Incorrect permission for send. Got %v, expected %v\n", v, send1 > 0)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..7b4a482de98338de53fadef719c551e44de82706
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go
@@ -0,0 +1,1259 @@
+package state
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"testing"
+	"time"
+
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
+	dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm"
+)
+
+/*
+Permission Tests:
+
+- SendTx:
+x	- 1 input, no perm, call perm, create perm
+x	- 1 input, perm
+x	- 2 inputs, one with perm one without
+
+- CallTx, CALL
+x	- 1 input, no perm, send perm, create perm
+x	- 1 input, perm
+x	- contract runs call but doesn't have call perm
+x	- contract runs call and has call perm
+x	- contract runs call (with perm), runs contract that runs call (without perm)
+x	- contract runs call (with perm), runs contract that runs call (with perm)
+
+- CallTx for Create, CREATE
+x	- 1 input, no perm, send perm, call perm
+x 	- 1 input, perm
+x	- contract runs create but doesn't have create perm
+x	- contract runs create but has perm
+x	- contract runs call with empty address (has call and create perm)
+
+- NameTx
+	- no perm, send perm, call perm
+	- with perm
+
+- BondTx
+x	- 1 input, no perm
+x	- 1 input, perm
+x	- 1 bonder with perm, input without send or bond
+x	- 1 bonder with perm, input with send
+x	- 1 bonder with perm, input with bond
+x	- 2 inputs, one with perm one without
+
+- SendTx for new account
+x 	- 1 input, 1 unknown ouput, input with send, not create  (fail)
+x 	- 1 input, 1 unknown ouput, input with send and create (pass)
+x 	- 2 inputs, 1 unknown ouput, both inputs with send, one with create, one without (fail)
+x 	- 2 inputs, 1 known output, 1 unknown ouput, one input with create, one without (fail)
+x 	- 2 inputs, 1 unknown ouput, both inputs with send, both inputs with create (pass )
+x 	- 2 inputs, 1 known output, 1 unknown ouput, both inputs with create, (pass)
+
+
+- CALL for new account
+x	- unknown output, without create (fail)
+x	- unknown output, with create (pass)
+
+
+- SNative (CallTx, CALL):
+	- for each of CallTx, Call
+x		- call each snative without permission, fails
+x		- call each snative with permission, pass
+	- list:
+x		- base: has,set,unset
+x		- globals: set
+x 		- roles: has, add, rm
+
+
+*/
+
+// keys
+var user = makeUsers(10)
+var chainID = "testchain"
+
+func makeUsers(n int) []*account.PrivAccount {
+	accounts := []*account.PrivAccount{}
+	for i := 0; i < n; i++ {
+		secret := []byte("mysecret" + strconv.Itoa(i))
+		user := account.GenPrivAccountFromSecret(secret)
+		accounts = append(accounts, user)
+	}
+	return accounts
+}
+
+var (
+	PermsAllFalse = ptypes.NewAccountPermissions()
+)
+
+func newBaseGenDoc(globalPerm, accountPerm *ptypes.AccountPermissions) GenesisDoc {
+	genAccounts := []GenesisAccount{}
+	for _, u := range user[:5] {
+		genAccounts = append(genAccounts, GenesisAccount{
+			Address:     u.Address,
+			Amount:      1000000,
+			Permissions: accountPerm.Copy(),
+		})
+	}
+
+	return GenesisDoc{
+		GenesisTime: time.Now(),
+		ChainID:     chainID,
+		Params: &GenesisParams{
+			GlobalPermissions: globalPerm,
+		},
+		Accounts: genAccounts,
+		Validators: []GenesisValidator{
+			GenesisValidator{
+				PubKey: user[0].PubKey.(account.PubKeyEd25519),
+				Amount: 10,
+				UnbondTo: []BasicAccount{
+					BasicAccount{
+						Address: user[0].Address,
+					},
+				},
+			},
+		},
+	}
+}
+
+func TestSendFails(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)
+	genDoc.Accounts[2].Permissions.Base.Set(ptypes.Call, true)
+	genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//-------------------
+	// send txs
+
+	// simple send tx should fail
+	tx := types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple send tx with call perm should fail
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[4].Address, 5)
+	tx.SignInput(chainID, 0, user[2])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple send tx with create perm should fail
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[4].Address, 5)
+	tx.SignInput(chainID, 0, user[3])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple send tx to unknown account without create_account perm should fail
+	acc := blockCache.GetAccount(user[3].Address)
+	acc.Permissions.Base.Set(ptypes.Send, true)
+	blockCache.UpdateAccount(acc)
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[6].Address, 5)
+	tx.SignInput(chainID, 0, user[3])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+}
+
+func TestName(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true)
+	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Name, true)
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//-------------------
+	// name txs
+
+	// simple name tx without perm should fail
+	tx, err := types.NewNameTx(st, user[0].PubKey, "somename", "somedata", 10000, 100)
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Sign(chainID, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple name tx with perm should pass
+	tx, err = types.NewNameTx(st, user[1].PubKey, "somename", "somedata", 10000, 100)
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Sign(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestCallFails(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)
+	genDoc.Accounts[2].Permissions.Base.Set(ptypes.Call, true)
+	genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//-------------------
+	// call txs
+
+	// simple call tx should fail
+	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, user[4].Address, nil, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call tx with send permission should fail
+	tx, _ = types.NewCallTx(blockCache, user[1].PubKey, user[4].Address, nil, 100, 100, 100)
+	tx.Sign(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call tx with create permission should fail
+	tx, _ = types.NewCallTx(blockCache, user[3].PubKey, user[4].Address, nil, 100, 100, 100)
+	tx.Sign(chainID, user[3])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	//-------------------
+	// create txs
+
+	// simple call create tx should fail
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, nil, nil, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call create tx with send perm should fail
+	tx, _ = types.NewCallTx(blockCache, user[1].PubKey, nil, nil, 100, 100, 100)
+	tx.Sign(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call create tx with call perm should fail
+	tx, _ = types.NewCallTx(blockCache, user[2].PubKey, nil, nil, 100, 100, 100)
+	tx.Sign(chainID, user[2])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+}
+
+func TestSendPermission(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true) // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	// A single input, having the permission, should succeed
+	tx := types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+
+	// Two inputs, one with permission, one without, should fail
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[2].Address, 10)
+	tx.SignInput(chainID, 0, user[0])
+	tx.SignInput(chainID, 1, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+}
+
+func TestCallPermission(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//------------------------------
+	// call to simple contract
+	fmt.Println("##### SIMPLE CONTRACT")
+
+	// create simple contract
+	simpleContractAddr := NewContractAddress(user[0].Address, 100)
+	simpleAcc := &account.Account{
+		Address:     simpleContractAddr,
+		Balance:     0,
+		Code:        []byte{0x60},
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: ptypes.NewAccountPermissions(),
+	}
+	st.UpdateAccount(simpleAcc)
+
+	// A single input, having the permission, should succeed
+	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, simpleContractAddr, nil, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls simple contract - without perm
+	fmt.Println("##### CALL TO SIMPLE CONTRACT (FAIL)")
+
+	// create contract that calls the simple contract
+	contractCode := callContractCode(simpleContractAddr)
+	caller1ContractAddr := NewContractAddress(user[0].Address, 101)
+	caller1Acc := &account.Account{
+		Address:     caller1ContractAddr,
+		Balance:     0,
+		Code:        contractCode,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: ptypes.NewAccountPermissions(),
+	}
+	blockCache.UpdateAccount(caller1Acc)
+
+	// A single input, having the permission, but the contract doesn't have permission
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls simple contract - with perm
+	fmt.Println("##### CALL TO SIMPLE CONTRACT (PASS)")
+
+	// A single input, having the permission, and the contract has permission
+	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
+	blockCache.UpdateAccount(caller1Acc)
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception:", exception)
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls contract that calls simple contract - without perm
+	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
+	// caller1Contract does not have call perms, but caller2Contract does.
+	fmt.Println("##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (FAIL)")
+
+	contractCode2 := callContractCode(caller1ContractAddr)
+	caller2ContractAddr := NewContractAddress(user[0].Address, 102)
+	caller2Acc := &account.Account{
+		Address:     caller2ContractAddr,
+		Balance:     1000,
+		Code:        contractCode2,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: ptypes.NewAccountPermissions(),
+	}
+	caller1Acc.Permissions.Base.Set(ptypes.Call, false)
+	caller2Acc.Permissions.Base.Set(ptypes.Call, true)
+	blockCache.UpdateAccount(caller1Acc)
+	blockCache.UpdateAccount(caller2Acc)
+
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls contract that calls simple contract - without perm
+	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
+	// both caller1 and caller2 have permission
+	fmt.Println("##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (PASS)")
+
+	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
+	blockCache.UpdateAccount(caller1Acc)
+
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception", exception)
+	}
+}
+
+func TestCreatePermission(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.CreateContract, true) // give the 0 account permission
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true)           // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//------------------------------
+	// create a simple contract
+	fmt.Println("##### CREATE SIMPLE CONTRACT")
+
+	contractCode := []byte{0x60}
+	createCode := wrapContractForCreate(contractCode)
+
+	// A single input, having the permission, should succeed
+	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, nil, createCode, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+	// ensure the contract is there
+	contractAddr := NewContractAddress(tx.Input.Address, uint64(tx.Input.Sequence))
+	contractAcc := blockCache.GetAccount(contractAddr)
+	if contractAcc == nil {
+		t.Fatalf("failed to create contract %X", contractAddr)
+	}
+	if bytes.Compare(contractAcc.Code, contractCode) != 0 {
+		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code, contractCode)
+	}
+
+	//------------------------------
+	// create contract that uses the CREATE op
+	fmt.Println("##### CREATE FACTORY")
+
+	contractCode = []byte{0x60}
+	createCode = wrapContractForCreate(contractCode)
+	factoryCode := createContractCode()
+	createFactoryCode := wrapContractForCreate(factoryCode)
+
+	// A single input, having the permission, should succeed
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, nil, createFactoryCode, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+	// ensure the contract is there
+	contractAddr = NewContractAddress(tx.Input.Address, uint64(tx.Input.Sequence))
+	contractAcc = blockCache.GetAccount(contractAddr)
+	if contractAcc == nil {
+		t.Fatalf("failed to create contract %X", contractAddr)
+	}
+	if bytes.Compare(contractAcc.Code, factoryCode) != 0 {
+		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code, factoryCode)
+	}
+
+	//------------------------------
+	// call the contract (should FAIL)
+	fmt.Println("###### CALL THE FACTORY (FAIL)")
+
+	// A single input, having the permission, should succeed
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(contractAddr)) //
+	if exception == "" {
+		t.Fatal("expected exception")
+	}
+
+	//------------------------------
+	// call the contract (should PASS)
+	fmt.Println("###### CALL THE FACTORY (PASS)")
+
+	contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
+	blockCache.UpdateAccount(contractAcc)
+
+	// A single input, having the permission, should succeed
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
+	tx.Sign(chainID, user[0])
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(contractAddr)) //
+	if exception != "" {
+		t.Fatal("unexpected exception", exception)
+	}
+
+	//--------------------------------
+	fmt.Println("##### CALL to empty address")
+	zeroAddr := LeftPadBytes([]byte{}, 20)
+	code := callContractCode(zeroAddr)
+
+	contractAddr = NewContractAddress(user[0].Address, 110)
+	contractAcc = &account.Account{
+		Address:     contractAddr,
+		Balance:     1000,
+		Code:        code,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: ptypes.NewAccountPermissions(),
+	}
+	contractAcc.Permissions.Base.Set(ptypes.Call, true)
+	contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
+	blockCache.UpdateAccount(contractAcc)
+
+	// this should call the 0 address but not create ...
+	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(zeroAddr)) //
+	if exception != "" {
+		t.Fatal("unexpected exception", exception)
+	}
+	zeroAcc := blockCache.GetAccount(zeroAddr)
+	if len(zeroAcc.Code) != 0 {
+		t.Fatal("the zero account was given code from a CALL!")
+	}
+}
+
+func TestBondPermission(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+	var bondAcc *account.Account
+
+	//------------------------------
+	// one bonder without permission should fail
+	tx, _ := types.NewBondTx(user[1].PubKey)
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[1])
+	tx.SignBond(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	//------------------------------
+	// one bonder with permission should pass
+	bondAcc = blockCache.GetAccount(user[1].Address)
+	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
+	blockCache.UpdateAccount(bondAcc)
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	blockCache = NewBlockCache(st)
+	bondAcc = blockCache.GetAccount(user[1].Address)
+	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
+	blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input without send should fail
+	tx, _ = types.NewBondTx(user[1].PubKey)
+	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[2])
+	tx.SignBond(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	blockCache = NewBlockCache(st)
+	bondAcc = blockCache.GetAccount(user[1].Address)
+	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
+	blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input with send should pass
+	sendAcc := blockCache.GetAccount(user[2].Address)
+	sendAcc.Permissions.Base.Set(ptypes.Send, true)
+	blockCache.UpdateAccount(sendAcc)
+	tx, _ = types.NewBondTx(user[1].PubKey)
+	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[2])
+	tx.SignBond(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	blockCache = NewBlockCache(st)
+	bondAcc = blockCache.GetAccount(user[1].Address)
+	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
+	blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input with bond should pass
+	sendAcc.Permissions.Base.Set(ptypes.Bond, true)
+	blockCache.UpdateAccount(sendAcc)
+	tx, _ = types.NewBondTx(user[1].PubKey)
+	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[2])
+	tx.SignBond(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	blockCache = NewBlockCache(st)
+	bondAcc = blockCache.GetAccount(user[1].Address)
+	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
+	blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input from that bonder and an input without send or bond should fail
+	tx, _ = types.NewBondTx(user[1].PubKey)
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[1].Address, 5)
+	tx.SignInput(chainID, 0, user[1])
+	tx.SignInput(chainID, 1, user[2])
+	tx.SignBond(chainID, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	}
+}
+
+func TestCreateAccountPermission(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true)          // give the 0 account permission
+	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)          // give the 0 account permission
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.CreateAccount, true) // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//----------------------------------------------------------
+	// SendTx to unknown account
+
+	// A single input, having the permission, should succeed
+	tx := types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[6].Address, 5)
+	tx.SignInput(chainID, 0, user[0])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+
+	// Two inputs, both with send, one with create, one without, should fail
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[7].Address, 10)
+	tx.SignInput(chainID, 0, user[0])
+	tx.SignInput(chainID, 1, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// Two inputs, both with send, one with create, one without, two ouputs (one known, one unknown) should fail
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[7].Address, 4)
+	tx.AddOutput(user[4].Address, 6)
+	tx.SignInput(chainID, 0, user[0])
+	tx.SignInput(chainID, 1, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// Two inputs, both with send, both with create, should pass
+	acc := blockCache.GetAccount(user[1].Address)
+	acc.Permissions.Base.Set(ptypes.CreateAccount, true)
+	blockCache.UpdateAccount(acc)
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[7].Address, 10)
+	tx.SignInput(chainID, 0, user[0])
+	tx.SignInput(chainID, 1, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// Two inputs, both with send, both with create, two outputs (one known, one unknown) should pass
+	tx = types.NewSendTx()
+	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(user[7].Address, 7)
+	tx.AddOutput(user[4].Address, 3)
+	tx.SignInput(chainID, 0, user[0])
+	tx.SignInput(chainID, 1, user[1])
+	if err := ExecTx(blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	//----------------------------------------------------------
+	// CALL to unknown account
+
+	acc = blockCache.GetAccount(user[0].Address)
+	acc.Permissions.Base.Set(ptypes.Call, true)
+	blockCache.UpdateAccount(acc)
+
+	// call to contract that calls unknown account - without create_account perm
+	// create contract that calls the simple contract
+	contractCode := callContractCode(user[9].Address)
+	caller1ContractAddr := NewContractAddress(user[4].Address, 101)
+	caller1Acc := &account.Account{
+		Address:     caller1ContractAddr,
+		Balance:     0,
+		Code:        contractCode,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: ptypes.NewAccountPermissions(),
+	}
+	blockCache.UpdateAccount(caller1Acc)
+
+	// A single input, having the permission, but the contract doesn't have permission
+	txCall, _ := types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
+	txCall.Sign(chainID, user[0])
+
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception := execTxWaitEvent(t, blockCache, txCall, types.EventStringAccReceive(caller1ContractAddr)) //
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+
+	// NOTE: for a contract to be able to CreateAccount, it must be able to call
+	// NOTE: for a user to be able to CreateAccount, it must be able to send!
+	caller1Acc.Permissions.Base.Set(ptypes.CreateAccount, true)
+	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
+	blockCache.UpdateAccount(caller1Acc)
+	// A single input, having the permission, but the contract doesn't have permission
+	txCall, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
+	txCall.Sign(chainID, user[0])
+
+	// we need to subscribe to the Receive event to detect the exception
+	_, exception = execTxWaitEvent(t, blockCache, txCall, types.EventStringAccReceive(caller1ContractAddr)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception", exception)
+	}
+
+}
+
+func TestSNativeCALL(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
+	genDoc.Accounts[3].Permissions.Base.Set(ptypes.Bond, true) // some arbitrary permission to play with
+	genDoc.Accounts[3].Permissions.AddRole("bumble")
+	genDoc.Accounts[3].Permissions.AddRole("bee")
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//----------------------------------------------------------
+	// Test CALL to SNative contracts
+
+	// make the main contract once
+	doug := &account.Account{
+		Address:     ptypes.DougAddress,
+		Balance:     0,
+		Code:        nil,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: ptypes.NewAccountPermissions(),
+	}
+	doug.Permissions.Base.Set(ptypes.Call, true)
+	blockCache.UpdateAccount(doug)
+
+	fmt.Println("#### hasBasePerm")
+	// hasBasePerm
+	snativeAddress, data := snativePermTestInput("hasBasePerm", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### setBasePerm")
+	// setBasePerm
+	snativeAddress, data = snativePermTestInput("setBasePerm", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+	snativeAddress, data = snativePermTestInput("setBasePerm", user[3], ptypes.CreateContract, true)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### unsetBasePerm")
+	// unsetBasePerm
+	snativeAddress, data = snativePermTestInput("unsetBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### setGlobalPerm")
+	// setGlobalPerm
+	snativeAddress, data = snativePermTestInput("setGlobalPerm", user[3], ptypes.CreateContract, true)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	// clearBasePerm
+	// TODO
+
+	fmt.Println("#### hasRole")
+	// hasRole
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "bumble")
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### addRole")
+	// addRole
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+	snativeAddress, data = snativeRoleTestInput("addRole", user[3], "chuck")
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### rmRole")
+	// rmRole
+	snativeAddress, data = snativeRoleTestInput("rmRole", user[3], "chuck")
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+}
+
+func TestSNativeCallTx(t *testing.T) {
+	stateDB := dbm.GetDB("state")
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
+	genDoc.Accounts[3].Permissions.Base.Set(ptypes.Bond, true) // some arbitrary permission to play with
+	genDoc.Accounts[3].Permissions.AddRole("bumble")
+	genDoc.Accounts[3].Permissions.AddRole("bee")
+	st := MakeGenesisState(stateDB, &genDoc)
+	blockCache := NewBlockCache(st)
+
+	//----------------------------------------------------------
+	// Test CallTx to SNative contracts
+	var doug *account.Account = nil
+
+	fmt.Println("#### hasBasePerm")
+	// hasBasePerm
+	snativeAddress, data := snativePermTestInput("hasBasePerm", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### setBasePerm")
+	// setBasePerm
+	snativeAddress, data = snativePermTestInput("setBasePerm", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+	snativeAddress, data = snativePermTestInput("setBasePerm", user[3], ptypes.CreateContract, true)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### unsetBasePerm")
+	// unsetBasePerm
+	snativeAddress, data = snativePermTestInput("unsetBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### setGlobalPerm")
+	// setGlobalPerm
+	snativeAddress, data = snativePermTestInput("setGlobalPerm", user[3], ptypes.CreateContract, true)
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativePermTestInput("hasBasePerm", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	// clearBasePerm
+	// TODO
+
+	fmt.Println("#### hasRole")
+	// hasRole
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "bumble")
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### addRole")
+	// addRole
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+	snativeAddress, data = snativeRoleTestInput("addRole", user[3], "chuck")
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("#### rmRole")
+	// rmRole
+	snativeAddress, data = snativeRoleTestInput("rmRole", user[3], "chuck")
+	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, data = snativeRoleTestInput("hasRole", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+}
+
+//-------------------------------------------------------------------------------------
+// helpers
+
+// run ExecTx and wait for the Receive event on given addr
+// returns the msg data and an error/exception
+func execTxWaitEvent(t *testing.T, blockCache *BlockCache, tx types.Tx, eventid string) (interface{}, string) {
+	evsw := new(events.EventSwitch)
+	evsw.Start()
+	ch := make(chan interface{})
+	evsw.AddListenerForEvent("test", eventid, func(msg interface{}) {
+		ch <- msg
+	})
+	evc := events.NewEventCache(evsw)
+	go func() {
+		if err := ExecTx(blockCache, tx, true, evc); err != nil {
+			ch <- err.Error()
+		}
+		evc.Flush()
+	}()
+	msg := <-ch
+	switch ev := msg.(type) {
+	case types.EventMsgCallTx:
+		return ev, ev.Exception
+	case types.EventMsgCall:
+		return ev, ev.Exception
+	case string:
+		return nil, ev
+	default:
+		return ev, ""
+	}
+}
+
+// give a contract perms for an snative, call it, it calls the snative, ensure the check funciton (f) succeeds
+func testSNativeCALLExpectPass(t *testing.T, blockCache *BlockCache, doug *account.Account, snativeAddress, data []byte, f func([]byte) error) {
+	perm := vm.RegisteredSNativePermissions[LeftPadWord256(snativeAddress)]
+	var addr []byte
+	if doug != nil {
+		contractCode := callContractCode(snativeAddress)
+		doug.Code = contractCode
+		doug.Permissions.Base.Set(perm, true)
+		blockCache.UpdateAccount(doug)
+		addr = doug.Address
+	} else {
+		acc := blockCache.GetAccount(user[0].Address)
+		acc.Permissions.Base.Set(perm, true)
+		blockCache.UpdateAccount(acc)
+		addr = snativeAddress
+	}
+	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, addr, data, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+	ev, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(snativeAddress)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception", exception)
+	}
+	evv := ev.(types.EventMsgCall)
+	ret := evv.Return
+	if err := f(ret); err != nil {
+		t.Fatal(err)
+	}
+}
+
+// assumes the contract has not been given the permission. calls the it, it calls the snative, expects to fail
+func testSNativeCALLExpectFail(t *testing.T, blockCache *BlockCache, doug *account.Account, snativeAddress, data []byte) {
+	var addr []byte
+	if doug != nil {
+		contractCode := callContractCode(snativeAddress)
+		doug.Code = contractCode
+		blockCache.UpdateAccount(doug)
+		addr = doug.Address
+	} else {
+		addr = snativeAddress
+	}
+	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, addr, data, 100, 10000, 100)
+	tx.Sign(chainID, user[0])
+	fmt.Println("subscribing to", types.EventStringAccReceive(snativeAddress))
+	_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(snativeAddress))
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+}
+
+func boolToWord256(v bool) Word256 {
+	var vint byte
+	if v {
+		vint = 0x1
+	} else {
+		vint = 0x0
+	}
+	return LeftPadWord256([]byte{vint})
+}
+
+func snativePermTestInput(name string, user *account.PrivAccount, perm ptypes.PermFlag, val bool) (addr []byte, data []byte) {
+	addr = LeftPadWord256([]byte(name)).Postfix(20)
+	switch name {
+	case "hasBasePerm", "unsetBasePerm":
+		data = LeftPadBytes(user.Address, 32)
+		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
+	case "setBasePerm":
+		data = LeftPadBytes(user.Address, 32)
+		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
+		data = append(data, boolToWord256(val).Bytes()...)
+	case "setGlobalPerm":
+		data = Uint64ToWord256(uint64(perm)).Bytes()
+		data = append(data, boolToWord256(val).Bytes()...)
+	case "clearBasePerm":
+	}
+	return
+}
+
+func snativeRoleTestInput(name string, user *account.PrivAccount, role string) (addr []byte, data []byte) {
+	addr = LeftPadWord256([]byte(name)).Postfix(20)
+	data = LeftPadBytes(user.Address, 32)
+	data = append(data, LeftPadBytes([]byte(role), 32)...)
+	return
+}
+
+// convenience function for contract that calls a given address
+func callContractCode(contractAddr []byte) []byte {
+	// calldatacopy into mem and use as input to call
+	memOff, inputOff := byte(0x0), byte(0x0)
+	contractCode := []byte{0x36, 0x60, inputOff, 0x60, memOff, 0x37}
+
+	gas1, gas2 := byte(0x1), byte(0x1)
+	value := byte(0x1)
+	inOff := byte(0x0)
+	retOff, retSize := byte(0x0), byte(0x20)
+	// this is the code we want to run (call a contract and return)
+	contractCode = append(contractCode, []byte{0x60, retSize, 0x60, retOff, 0x36, 0x60, inOff, 0x60, value, 0x73}...)
+	contractCode = append(contractCode, contractAddr...)
+	contractCode = append(contractCode, []byte{0x61, gas1, gas2, 0xf1, 0x60, 0x20, 0x60, 0x0, 0xf3}...)
+	return contractCode
+}
+
+// convenience function for contract that is a factory for the code that comes as call data
+func createContractCode() []byte {
+	// TODO: gas ...
+
+	// calldatacopy the calldatasize
+	memOff, inputOff := byte(0x0), byte(0x0)
+	contractCode := []byte{0x60, memOff, 0x60, inputOff, 0x36, 0x37}
+
+	// create
+	value := byte(0x1)
+	contractCode = append(contractCode, []byte{0x60, value, 0x36, 0x60, memOff, 0xf0}...)
+	return contractCode
+}
+
+// wrap a contract in create code
+func wrapContractForCreate(contractCode []byte) []byte {
+	// the is the code we need to return the contractCode when the contract is initialized
+	lenCode := len(contractCode)
+	// push code to the stack
+	code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
+	// store it in memory
+	code = append(code, []byte{0x60, 0x0, 0x52}...)
+	// return whats in memory
+	code = append(code, []byte{0x60, byte(lenCode), 0x60, 0x0, 0xf3}...)
+	// return init code, contract code, expected return
+	return code
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go
index 68f28a89f8985e073c7a4e927850f6dbd78b0797..0743a002861b258443f18d3f939ad6cad40a5e9e 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go
@@ -142,6 +142,10 @@ func (s *State) SetBlockStateHash(block *types.Block) error {
 	return nil
 }
 
+func (s *State) SetDB(db dbm.DB) {
+	s.DB = db
+}
+
 //-------------------------------------
 // State.accounts
 
@@ -175,6 +179,11 @@ func (s *State) GetAccounts() merkle.Tree {
 	return s.accounts.Copy()
 }
 
+// Set the accounts tree
+func (s *State) SetAccounts(accounts merkle.Tree) {
+	s.accounts = accounts
+}
+
 // State.accounts
 //-------------------------------------
 // State.validators
@@ -196,6 +205,10 @@ func (s *State) SetValidatorInfo(valInfo *ValidatorInfo) (updated bool) {
 	return s.validatorInfos.Set(valInfo.Address, valInfo.Copy())
 }
 
+func (s *State) GetValidatorInfos() merkle.Tree {
+	return s.validatorInfos.Copy()
+}
+
 func (s *State) unbondValidator(val *Validator) {
 	// Move validator to UnbondingValidators
 	val, removed := s.BondedValidators.Remove(val.Address)
@@ -232,7 +245,7 @@ func (s *State) releaseValidator(val *Validator) {
 	s.SetValidatorInfo(valInfo)
 
 	// Send coins back to UnbondTo outputs
-	accounts, err := getOrMakeAccounts(s, nil, valInfo.UnbondTo)
+	accounts, err := getOrMakeOutputs(s, nil, valInfo.UnbondTo)
 	if err != nil {
 		panic("Couldn't get or make unbondTo accounts")
 	}
@@ -269,6 +282,11 @@ func (s *State) destroyValidator(val *Validator) {
 
 }
 
+// Set the validator infos tree
+func (s *State) SetValidatorInfos(validatorInfos merkle.Tree) {
+	s.validatorInfos = validatorInfos
+}
+
 // State.validators
 //-------------------------------------
 // State.storage
@@ -305,6 +323,11 @@ func (s *State) GetNames() merkle.Tree {
 	return s.nameReg.Copy()
 }
 
+// Set the name reg tree
+func (s *State) SetNameReg(nameReg merkle.Tree) {
+	s.nameReg = nameReg
+}
+
 func NameRegEncoder(o interface{}, w io.Writer, n *int64, err *error) {
 	binary.WriteBinary(o.(*types.NameRegEntry), w, n, err)
 }
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go
index 38a4cdc9b44b00d1e86c650571a605e9c745644a..b9fae8868ce8f5b741a9bf61a5439c88752d20aa 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go
@@ -7,6 +7,7 @@ import (
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 
 	"io/ioutil"
@@ -24,11 +25,13 @@ func Tempfile(prefix string) (*os.File, string) {
 
 func RandAccount(randBalance bool, minBalance uint64) (*account.Account, *account.PrivAccount) {
 	privAccount := account.GenPrivAccount()
+	perms := ptypes.NewDefaultAccountPermissions()
 	acc := &account.Account{
-		Address:  privAccount.PubKey.Address(),
-		PubKey:   privAccount.PubKey,
-		Sequence: RandUint(),
-		Balance:  minBalance,
+		Address:     privAccount.PubKey.Address(),
+		PubKey:      privAccount.PubKey,
+		Sequence:    RandUint(),
+		Balance:     minBalance,
+		Permissions: perms,
 	}
 	if randBalance {
 		acc.Balance += uint64(RandUint32())
@@ -73,8 +76,9 @@ func RandGenesisState(numAccounts int, randBalance bool, minBalance uint64, numV
 	for i := 0; i < numAccounts; i++ {
 		account, privAccount := RandAccount(randBalance, minBalance)
 		accounts[i] = GenesisAccount{
-			Address: account.Address,
-			Amount:  account.Balance,
+			Address:     account.Address,
+			Amount:      account.Balance,
+			Permissions: ptypes.NewDefaultAccountPermissions(),
 		}
 		privAccounts[i] = privAccount
 	}
@@ -85,7 +89,7 @@ func RandGenesisState(numAccounts int, randBalance bool, minBalance uint64, numV
 		validators[i] = GenesisValidator{
 			PubKey: valInfo.PubKey,
 			Amount: valInfo.FirstBondAmount,
-			UnbondTo: []GenesisAccount{
+			UnbondTo: []BasicAccount{
 				{
 					Address: valInfo.PubKey.Address(),
 					Amount:  valInfo.FirstBondAmount,
@@ -100,6 +104,9 @@ func RandGenesisState(numAccounts int, randBalance bool, minBalance uint64, numV
 		ChainID:     "tendermint_test",
 		Accounts:    accounts,
 		Validators:  validators,
+		Params: &GenesisParams{
+			GlobalPermissions: ptypes.NewDefaultAccountPermissions(),
+		},
 	})
 	s0.Save()
 	return s0, privAccounts, privValidators
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache.go
index 6ff1a634fb1c796b01a6d7ec0ee5346d553063d9..8b8c371a209e2159f36e66d9c22eef1afd353bee 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache.go
@@ -3,6 +3,7 @@ package state
 import (
 	ac "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" // for GlobalPermissionAddress ...
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/sha3"
 )
@@ -79,6 +80,8 @@ func (cache *TxCache) CreateAccount(creator *vm.Account) *vm.Account {
 			Code:        nil,
 			Nonce:       0,
 			StorageRoot: Zero256,
+			Permissions: cache.GetAccount(ptypes.GlobalPermissionsAddress256).Permissions,
+			Other:       nil,
 		}
 		cache.accounts[addr] = vmAccountInfo{account, false}
 		return account
@@ -159,6 +162,7 @@ func toVMAccount(acc *ac.Account) *vm.Account {
 		Code:        acc.Code, // This is crazy.
 		Nonce:       uint64(acc.Sequence),
 		StorageRoot: LeftPadWord256(acc.StorageRoot),
+		Permissions: acc.Permissions.Copy(),
 		Other:       acc.PubKey,
 	}
 }
@@ -169,6 +173,7 @@ func toStateAccount(acc *vm.Account) *ac.Account {
 	if !ok {
 		pubKey = nil
 	}
+
 	var storageRoot []byte
 	if acc.StorageRoot.IsZero() {
 		storageRoot = nil
@@ -182,6 +187,7 @@ func toStateAccount(acc *vm.Account) *ac.Account {
 		Code:        acc.Code,
 		Sequence:    uint(acc.Nonce),
 		StorageRoot: storageRoot,
+		Permissions: acc.Permissions,
 	}
 }
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/native.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/native.go
index cc8c3005755097de4967ff78acf99324cf9df724..9b9337f92cd93e2be7becf4ff48ad012c9a88b90 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/native.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/native.go
@@ -52,10 +52,8 @@ func sha256Func(input []byte, gas *uint64) (output []byte, err error) {
 	}
 	// Hash
 	hasher := sha256.New()
-	_, err = hasher.Write(input)
-	if err != nil {
-		panic(err)
-	}
+	// CONTRACT: this does not err
+	hasher.Write(input)
 	return hasher.Sum(nil), nil
 }
 
@@ -69,10 +67,8 @@ func ripemd160Func(input []byte, gas *uint64) (output []byte, err error) {
 	}
 	// Hash
 	hasher := ripemd160.New()
-	_, err = hasher.Write(input)
-	if err != nil {
-		panic(err)
-	}
+	// CONTRACT: this does not err
+	hasher.Write(input)
 	return LeftPadBytes(hasher.Sum(nil), 32), nil
 }
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/opcodes.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/opcodes.go
index a20f2a01c24194d9ff4cc17714c91f9af7bd030d..505d536cf2ced18767aaebffb3c00b9cc3ead2d1 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/opcodes.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/opcodes.go
@@ -7,8 +7,8 @@ import (
 
 type OpCode byte
 
-// Op codes
 const (
+	// Op codes
 	// 0x0 range - arithmetic ops
 	STOP OpCode = iota
 	ADD
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go
new file mode 100644
index 0000000000000000000000000000000000000000..73165be40ff1b8dc07b29fe648b03e7585dcada1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go
@@ -0,0 +1,259 @@
+package vm
+
+import (
+	"fmt"
+
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
+)
+
+//------------------------------------------------------------------------------------------------
+// Registered SNative contracts
+
+var RegisteredSNativeContracts = map[Word256]SNativeContract{
+	LeftPadWord256([]byte("hasBasePerm")):   hasBasePerm,
+	LeftPadWord256([]byte("setBasePerm")):   setBasePerm,
+	LeftPadWord256([]byte("unsetBasePerm")): unsetBasePerm,
+	LeftPadWord256([]byte("setGlobalPerm")): setGlobalPerm,
+	LeftPadWord256([]byte("hasRole")):       hasRole,
+	LeftPadWord256([]byte("addRole")):       addRole,
+	LeftPadWord256([]byte("rmRole")):        rmRole,
+}
+
+// Takes an appState so it can lookup/update accounts,
+// an account to check for permission to access the snative contract
+// and some input bytes (presumably 32byte words)
+type SNativeContract func(appState AppState, acc *Account, input []byte) (output []byte, err error)
+
+//-----------------------------------------------------------------------------
+// snative are native contracts that can access and manipulate the chain state
+// (in particular the permissions values)
+
+// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
+
+func hasBasePerm(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.HasBasePerm) {
+		return nil, ErrInvalidPermission{acc.Address, "HasBasePerm"}
+	}
+	if len(args) != 2*32 {
+		return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permission number)")
+	}
+	addr, permNum := returnTwoArgs(args)
+	vmAcc := appState.GetAccount(addr)
+	if vmAcc == nil {
+		return nil, fmt.Errorf("Unknown account %X", addr)
+	}
+	permN := ptypes.PermFlag(Uint64FromWord256(permNum)) // already shifted
+	if !ValidPermN(permN) {
+		return nil, ptypes.ErrInvalidPermission(permN)
+	}
+	var permInt byte
+	if HasPermission(appState, vmAcc, permN) {
+		permInt = 0x1
+	} else {
+		permInt = 0x0
+	}
+	dbg.Printf("snative.hasBasePerm(0x%X, %b) = %v\n", addr.Postfix(20), permN, permInt)
+	return LeftPadWord256([]byte{permInt}).Bytes(), nil
+}
+
+func setBasePerm(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.SetBasePerm) {
+		return nil, ErrInvalidPermission{acc.Address, "SetBasePerm"}
+	}
+	if len(args) != 3*32 {
+		return nil, fmt.Errorf("setBasePerm() takes three arguments (address, permission number, permission value)")
+	}
+	addr, permNum, perm := returnThreeArgs(args)
+	vmAcc := appState.GetAccount(addr)
+	if vmAcc == nil {
+		return nil, fmt.Errorf("Unknown account %X", addr)
+	}
+	permN := ptypes.PermFlag(Uint64FromWord256(permNum))
+	if !ValidPermN(permN) {
+		return nil, ptypes.ErrInvalidPermission(permN)
+	}
+	permV := !perm.IsZero()
+	if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
+		return nil, err
+	}
+	appState.UpdateAccount(vmAcc)
+	dbg.Printf("snative.setBasePerm(0x%X, %b, %v)\n", addr.Postfix(20), permN, permV)
+	return perm.Bytes(), nil
+}
+
+func unsetBasePerm(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.UnsetBasePerm) {
+		return nil, ErrInvalidPermission{acc.Address, "UnsetBasePerm"}
+	}
+	if len(args) != 2*32 {
+		return nil, fmt.Errorf("unsetBasePerm() takes two arguments (address, permission number)")
+	}
+	addr, permNum := returnTwoArgs(args)
+	vmAcc := appState.GetAccount(addr)
+	if vmAcc == nil {
+		return nil, fmt.Errorf("Unknown account %X", addr)
+	}
+	permN := ptypes.PermFlag(Uint64FromWord256(permNum))
+	if !ValidPermN(permN) {
+		return nil, ptypes.ErrInvalidPermission(permN)
+	}
+	if err = vmAcc.Permissions.Base.Unset(permN); err != nil {
+		return nil, err
+	}
+	appState.UpdateAccount(vmAcc)
+	dbg.Printf("snative.unsetBasePerm(0x%X, %b)\n", addr.Postfix(20), permN)
+	return permNum.Bytes(), nil
+}
+
+func setGlobalPerm(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.SetGlobalPerm) {
+		return nil, ErrInvalidPermission{acc.Address, "SetGlobalPerm"}
+	}
+	if len(args) != 2*32 {
+		return nil, fmt.Errorf("setGlobalPerm() takes two arguments (permission number, permission value)")
+	}
+	permNum, perm := returnTwoArgs(args)
+	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
+	if vmAcc == nil {
+		panic("cant find the global permissions account")
+	}
+	permN := ptypes.PermFlag(Uint64FromWord256(permNum))
+	if !ValidPermN(permN) {
+		return nil, ptypes.ErrInvalidPermission(permN)
+	}
+	permV := !perm.IsZero()
+	if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
+		return nil, err
+	}
+	appState.UpdateAccount(vmAcc)
+	dbg.Printf("snative.setGlobalPerm(%b, %v)\n", permN, permV)
+	return perm.Bytes(), nil
+}
+
+// TODO: needs access to an iterator ...
+func clearPerm(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.ClearBasePerm) {
+		return nil, ErrInvalidPermission{acc.Address, "ClearPerm"}
+	}
+	return nil, nil
+}
+
+func hasRole(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.HasRole) {
+		return nil, ErrInvalidPermission{acc.Address, "HasRole"}
+	}
+	if len(args) != 2*32 {
+		return nil, fmt.Errorf("hasRole() takes two arguments (address, role)")
+	}
+	addr, role := returnTwoArgs(args)
+	vmAcc := appState.GetAccount(addr)
+	if vmAcc == nil {
+		return nil, fmt.Errorf("Unknown account %X", addr)
+	}
+	roleS := string(role.Bytes())
+	var permInt byte
+	if vmAcc.Permissions.HasRole(roleS) {
+		permInt = 0x1
+	} else {
+		permInt = 0x0
+	}
+	dbg.Printf("snative.hasRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
+	return LeftPadWord256([]byte{permInt}).Bytes(), nil
+}
+
+func addRole(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.AddRole) {
+		return nil, ErrInvalidPermission{acc.Address, "AddRole"}
+	}
+	if len(args) != 2*32 {
+		return nil, fmt.Errorf("addRole() takes two arguments (address, role)")
+	}
+	addr, role := returnTwoArgs(args)
+	vmAcc := appState.GetAccount(addr)
+	if vmAcc == nil {
+		return nil, fmt.Errorf("Unknown account %X", addr)
+	}
+	roleS := string(role.Bytes())
+	var permInt byte
+	if vmAcc.Permissions.AddRole(roleS) {
+		permInt = 0x1
+	} else {
+		permInt = 0x0
+	}
+	appState.UpdateAccount(vmAcc)
+	dbg.Printf("snative.addRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
+	return LeftPadWord256([]byte{permInt}).Bytes(), nil
+}
+
+func rmRole(appState AppState, acc *Account, args []byte) (output []byte, err error) {
+	if !HasPermission(appState, acc, ptypes.RmRole) {
+		return nil, ErrInvalidPermission{acc.Address, "RmRole"}
+	}
+	if len(args) != 2*32 {
+		return nil, fmt.Errorf("rmRole() takes two arguments (address, role)")
+	}
+	addr, role := returnTwoArgs(args)
+	vmAcc := appState.GetAccount(addr)
+	if vmAcc == nil {
+		return nil, fmt.Errorf("Unknown account %X", addr)
+	}
+	roleS := string(role.Bytes())
+	var permInt byte
+	if vmAcc.Permissions.RmRole(roleS) {
+		permInt = 0x1
+	} else {
+		permInt = 0x0
+	}
+	appState.UpdateAccount(vmAcc)
+	dbg.Printf("snative.rmRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
+	return LeftPadWord256([]byte{permInt}).Bytes(), nil
+}
+
+//------------------------------------------------------------------------------------------------
+// Errors and utility funcs
+
+type ErrInvalidPermission struct {
+	Address Word256
+	SNative string
+}
+
+func (e ErrInvalidPermission) Error() string {
+	return fmt.Sprintf("Account %X does not have permission snative.%s", e.Address.Postfix(20), e.SNative)
+}
+
+// Checks if a permission flag is valid (a known base chain or snative permission)
+func ValidPermN(n ptypes.PermFlag) bool {
+	if n > ptypes.TopBasePermission && n < ptypes.FirstSNativePerm {
+		return false
+	} else if n > ptypes.TopSNativePermission {
+		return false
+	}
+	return true
+}
+
+// assumes length has already been checked
+func returnTwoArgs(args []byte) (a Word256, b Word256) {
+	copy(a[:], args[:32])
+	copy(b[:], args[32:64])
+	return
+}
+
+// assumes length has already been checked
+func returnThreeArgs(args []byte) (a Word256, b Word256, c Word256) {
+	copy(a[:], args[:32])
+	copy(b[:], args[32:64])
+	copy(c[:], args[64:96])
+	return
+}
+
+// mostly a convenience for testing
+var RegisteredSNativePermissions = map[Word256]ptypes.PermFlag{
+	LeftPadWord256([]byte("hasBasePerm")):   ptypes.HasBasePerm,
+	LeftPadWord256([]byte("setBasePerm")):   ptypes.SetBasePerm,
+	LeftPadWord256([]byte("unsetBasePerm")): ptypes.UnsetBasePerm,
+	LeftPadWord256([]byte("setGlobalPerm")): ptypes.SetGlobalPerm,
+	LeftPadWord256([]byte("hasRole")):       ptypes.HasRole,
+	LeftPadWord256([]byte("addRole")):       ptypes.AddRole,
+	LeftPadWord256([]byte("rmRole")):        ptypes.RmRole,
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/stack.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/stack.go
index 7dd7d1743f2239ae8906817f22b22bcb404e7a32..2047a436d110e5b90cc1ff06d59365785b7e07e9 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/stack.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/stack.go
@@ -47,6 +47,7 @@ func (st *Stack) Push(d Word256) {
 	st.ptr++
 }
 
+// currently only called after Sha3
 func (st *Stack) PushBytes(bz []byte) {
 	if len(bz) != 32 {
 		panic("Invalid bytes size: expected 32")
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/test/vm_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/test/vm_test.go
index 246782316ba7e0afb40456f56df434b9478a7a99..7dd79cc5d0fc0176679fc27df0ec7d1d4442a1b1 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/test/vm_test.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/test/vm_test.go
@@ -53,9 +53,7 @@ func TestVM(t *testing.T) {
 	N := []byte{0x0f, 0x0f}
 	// Loop N times
 	code := []byte{0x60, 0x00, 0x60, 0x20, 0x52, 0x5B, byte(0x60 + len(N) - 1)}
-	for i := 0; i < len(N); i++ {
-		code = append(code, N[i])
-	}
+	code = append(code, N...)
 	code = append(code, []byte{0x60, 0x20, 0x51, 0x12, 0x15, 0x60, byte(0x1b + len(N)), 0x57, 0x60, 0x01, 0x60, 0x20, 0x51, 0x01, 0x60, 0x20, 0x52, 0x60, 0x05, 0x56, 0x5B}...)
 	start := time.Now()
 	output, err := ourVm.Call(account1, account2, code, []byte{}, 0, &gas)
@@ -120,6 +118,7 @@ func TestSendCall(t *testing.T) {
 
 	//----------------------------------------------
 	// account2 has insufficient balance, should fail
+	fmt.Println("Should fail with insufficient balance")
 
 	exception := runVMWaitEvents(t, ourVm, account1, account2, addr, contractCode, 1000)
 	if exception == "" {
@@ -137,6 +136,7 @@ func TestSendCall(t *testing.T) {
 
 	//----------------------------------------------
 	// insufficient gas, should fail
+	fmt.Println("Should fail with insufficient gas")
 
 	account2.Balance = 100000
 	exception = runVMWaitEvents(t, ourVm, account1, account2, addr, contractCode, 100)
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/types.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/types.go
index 4aa0964b59efb68b312aae7b8d98b174fcfeee51..6f744486c184d4519ae789e8a8b077398954c19c 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/types.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/types.go
@@ -2,6 +2,7 @@ package vm
 
 import (
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 )
 
 const (
@@ -15,6 +16,8 @@ type Account struct {
 	Nonce       uint64
 	StorageRoot Word256
 	Other       interface{} // For holding all other data.
+
+	Permissions *ptypes.AccountPermissions
 }
 
 func (acc *Account) String() string {
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go
index abfd855251c4e10e68fd465ea6004b5b7e8a9013..1a1e8874e169beedd587b6c34fa0e58bf38331d8 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go
@@ -8,6 +8,7 @@ import (
 
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
+	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/sha3"
 )
@@ -27,6 +28,14 @@ var (
 	ErrInvalidContract     = errors.New("Invalid contract")
 )
 
+type ErrPermission struct {
+	typ string
+}
+
+func (err ErrPermission) Error() string {
+	return fmt.Sprintf("Contract does not have permission to %s", err.typ)
+}
+
 type Debug bool
 
 const (
@@ -51,6 +60,9 @@ type VM struct {
 	callDepth int
 
 	evc events.Fireable
+
+	perms   bool // permission checking can be turned off
+	snative bool // access to snatives
 }
 
 func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM {
@@ -68,6 +80,32 @@ func (vm *VM) SetFireable(evc events.Fireable) {
 	vm.evc = evc
 }
 
+// to allow calls to native DougContracts (off by default)
+func (vm *VM) EnableSNatives() {
+	vm.snative = true
+}
+
+// run permission checks before call and create
+func (vm *VM) EnablePermissions() {
+	vm.perms = true
+}
+
+// XXX: it is the duty of the contract writer to call known permissions
+// we do not convey if a permission is not set
+// (unlike in state/execution, where we guarantee HasPermission is called
+// on known permissions and panics else)
+func HasPermission(appState AppState, acc *Account, perm ptypes.PermFlag) bool {
+	v, err := acc.Permissions.Base.Get(perm)
+	if _, ok := err.(ptypes.ErrValueNotSet); ok {
+		if appState == nil {
+			fmt.Printf("\n\n***** Unknown permission %b! ********\n\n", perm)
+			return false
+		}
+		return HasPermission(nil, appState.GetAccount(ptypes.GlobalPermissionsAddress256), perm)
+	}
+	return v
+}
+
 // CONTRACT appState is aware of caller and callee, so we can just mutate them.
 // value: To be transferred from caller to callee. Refunded upon error.
 // gas:   Available gas. No refunds for gas.
@@ -87,6 +125,17 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, ga
 		}
 	}()
 
+	// if code is empty, callee may be snative contract
+	if vm.snative && len(code) == 0 {
+		if snativeContract, ok := RegisteredSNativeContracts[callee.Address]; ok {
+			output, err = snativeContract(vm.appState, caller, input)
+			if err != nil {
+				*exception = err.Error()
+			}
+			return
+		}
+	}
+
 	if err = transfer(caller, callee, value); err != nil {
 		*exception = err.Error()
 		return
@@ -100,6 +149,7 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, ga
 			*exception = err.Error()
 			err := transfer(callee, caller, value)
 			if err != nil {
+				// data has been corrupted in ram
 				panic("Could not return value to caller")
 			}
 		}
@@ -658,6 +708,9 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
 			dbg.Printf(" => %v\n", log)
 
 		case CREATE: // 0xF0
+			if vm.perms && !HasPermission(vm.appState, callee, ptypes.CreateContract) {
+				return nil, ErrPermission{"create_contract"}
+			}
 			contractValue := stack.Pop64()
 			offset, size := stack.Pop64(), stack.Pop64()
 			input, ok := subslice(memory, offset, size)
@@ -683,6 +736,9 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
 			}
 
 		case CALL, CALLCODE: // 0xF1, 0xF2
+			if vm.perms && !HasPermission(vm.appState, callee, ptypes.Call) {
+				return nil, ErrPermission{"call"}
+			}
 			gasLimit := stack.Pop64()
 			addr, value := stack.Pop(), stack.Pop64()
 			inOffset, inSize := stack.Pop64(), stack.Pop64()   // inputs
@@ -726,10 +782,15 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
 					ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
 				} else {
 					if acc == nil {
-						// if we have not seen the account before, create it
-						// so we can send funds
-						acc = &Account{
-							Address: addr,
+						if _, ok := RegisteredSNativeContracts[addr]; vm.snative && ok {
+							acc = &Account{Address: addr}
+						} else {
+							// if we have not seen the account before, create it
+							// so we can send funds
+							if vm.perms && !HasPermission(vm.appState, caller, ptypes.CreateAccount) {
+								return nil, ErrPermission{"create_account"}
+							}
+							acc = &Account{Address: addr}
 						}
 						vm.appState.UpdateAccount(acc)
 					}
@@ -739,8 +800,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
 
 			// Push result
 			if err != nil {
-				dbg.Printf("error on call: %s", err.Error())
-				// TODO: fire event
+				dbg.Printf("error on call: %s\n", err.Error())
 				stack.Push(Zero256)
 			} else {
 				stack.Push(One256)
@@ -784,7 +844,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
 
 		default:
 			dbg.Printf("(pc) %-3v Invalid opcode %X\n", pc, op)
-			panic(fmt.Errorf("Invalid opcode %X", op))
+			return nil, fmt.Errorf("Invalid opcode %X", op)
 		}
 
 		pc++
diff --git a/circle.yml b/circle.yml
index 717733a9b39c4ef8619f0ab74e2fcbe2c10b4de9..66977f2bc5636a2deb925e51d9dccb3cb4326075 100644
--- a/circle.yml
+++ b/circle.yml
@@ -1,10 +1,30 @@
+machine:
+  post:
+    - rm -rf ${GOPATH%%:*}/src/github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}
+    - mkdir -p ${GOPATH%%:*}/src/github.com/${CIRCLE_PROJECT_USERNAME}
+    - cp -r ${HOME}/${CIRCLE_PROJECT_REPONAME} ${GOPATH%%:*}/src/github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}
+    - git config --global user.email "billings@erisindustries.com"
+    - git config --global user.name "Billings the Bot"
+
 dependencies:
   pre:
+    - sudo curl -L -o /usr/bin/docker 'http://s3-external-1.amazonaws.com/circle-downloads/docker-1.6.0-circleci'; chmod 0755 /usr/bin/docker; true
+    - sudo service docker start
     - "sudo apt-get update && sudo apt-get install -y libgmp3-dev"
+
   override:
     - "cd ./cmd/erisdb && go build"
     - "mv ~/eris-db/cmd/erisdb/erisdb ~/bin"
     - chmod +x ~/bin/erisdb
+
 test:
   override:
     - go test -v ./...
+
+deployment:
+  master:
+    branch: master
+    commands:
+      - docker build -t eris/erisdb:0.10 -f DOCKER/Dockerfile .
+      - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
+      - docker push eris/erisdb:0.10
diff --git a/erisdb/pipe/blockchain.go b/erisdb/pipe/blockchain.go
index b0704d7cf571a2fd192649420e7de16a2bbcd02b..19b11b892e94a0e93e4b69370c0fe19a1d5c5b1b 100644
--- a/erisdb/pipe/blockchain.go
+++ b/erisdb/pipe/blockchain.go
@@ -37,7 +37,7 @@ func newBlockchain(blockStore *bc.BlockStore) *blockchain {
 func (this *blockchain) Info() (*BlockchainInfo, error) {
 	chainId := config.GetString("chain_id")
 	db := dbm.NewMemDB()
-	genesisState := state.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
+	_, genesisState := state.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
 	genesisHash := genesisState.Hash()
 	latestHeight := this.blockStore.Height()
 
@@ -63,7 +63,7 @@ func (this *blockchain) ChainId() (string, error) {
 // Get the hash of the genesis block.
 func (this *blockchain) GenesisHash() ([]byte, error) {
 	db := dbm.NewMemDB()
-	genesisState := state.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
+	_, genesisState := state.MakeGenesisStateFromFile(db, config.GetString("genesis_file"))
 	return genesisState.Hash(), nil
 }