diff --git a/.gitignore b/.gitignore
index 062ac40a40e60a8deb295da0d715829b791ee5b6..c7f40537d814cb7864a2367604c295cfa919567c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,7 +9,6 @@ test_scratch/
 
 # Temporary / cached
 *.swp
-debug
 .idea
 .vscode
 
diff --git a/Makefile b/Makefile
index ba7048e3fe3d39db21a656fc2287e6eee95389e5..1ae718c5aeedf54a58bdf16974be15aac1a47122 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ SHELL := /bin/bash
 REPO := $(shell pwd)
 GOFILES_NOVENDOR := $(shell go list -f "{{.Dir}}" ./...)
 PACKAGES_NOVENDOR := $(shell go list ./...)
+COMMIT := $(shell git rev-parse --short HEAD)
 # Bosmarmot integration testing
 BOSMARMOT_PROJECT := github.com/monax/bosmarmot
 BOSMARMOT_GOPATH := ${REPO}/.gopath_bos
@@ -99,7 +100,7 @@ build_race:	check build_race_db build_race_client
 # build burrow
 .PHONY: build_db
 build_db:
-	go build -o ${REPO}/bin/burrow ./cmd/burrow
+	go build -ldflags "-X github.com/hyperledger/burrow/project.commit=${COMMIT}" -o ${REPO}/bin/burrow ./cmd/burrow
 
 # build burrow-client
 .PHONY: build_client
diff --git a/account/account.go b/account/account.go
index f17ceeaedb32312f0c8a89b3499dce15ed275094..ab6e987480246167cc4373884ac5bcfc7482a968 100644
--- a/account/account.go
+++ b/account/account.go
@@ -25,6 +25,8 @@ import (
 	"github.com/tendermint/go-wire"
 )
 
+var GlobalPermissionsAddress = Address(binary.Zero160)
+
 // Signable is an interface for all signable things.
 // It typically removes signatures before serializing.
 type Signable interface {
@@ -66,6 +68,8 @@ type Account interface {
 	// Obtain a deterministic serialisation of this account
 	// (i.e. update order and Go runtime independent)
 	Encode() ([]byte, error)
+	// String representation of the account
+	String() string
 }
 
 type MutableAccount interface {
@@ -214,14 +218,6 @@ func AsMutableAccount(account Account) MutableAccount {
 	return AsConcreteAccount(account).MutableAccount()
 }
 
-func GetMutableAccount(getter Getter, address Address) (MutableAccount, error) {
-	acc, err := getter.GetAccount(address)
-	if err != nil {
-		return nil, err
-	}
-	return AsMutableAccount(acc), nil
-}
-
 //----------------------------------------------
 // concreteAccount Wrapper
 
@@ -266,6 +262,10 @@ func (caw concreteAccountWrapper) Encode() ([]byte, error) {
 	return caw.ConcreteAccount.Encode()
 }
 
+func (caw concreteAccountWrapper) String() string {
+	return caw.ConcreteAccount.String()
+}
+
 func (caw concreteAccountWrapper) MarshalJSON() ([]byte, error) {
 	return json.Marshal(caw.ConcreteAccount)
 }
diff --git a/account/account_test.go b/account/account_test.go
index 800ea4ff8c4638a71fed54dc4f9defa79a7ec263..aaffb2ff882fb8b60a85e2160e40138f2cf8ce19 100644
--- a/account/account_test.go
+++ b/account/account_test.go
@@ -21,6 +21,8 @@ import (
 
 	"fmt"
 
+	"github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/permission/types"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"github.com/tendermint/go-crypto"
@@ -77,11 +79,20 @@ func TestAccountSerialise(t *testing.T) {
 
 func TestDecodeConcrete(t *testing.T) {
 	concreteAcc := NewConcreteAccountFromSecret("Super Semi Secret")
+	concreteAcc.Permissions = types.AccountPermissions{
+		Base: types.BasePermissions{
+			Perms:  permission.SetGlobal,
+			SetBit: permission.SetGlobal,
+		},
+		Roles: []string{"bums"},
+	}
 	acc := concreteAcc.Account()
 	encodedAcc, err := acc.Encode()
 	require.NoError(t, err)
+
 	concreteAccOut, err := DecodeConcrete(encodedAcc)
 	require.NoError(t, err)
+
 	assert.Equal(t, concreteAcc, *concreteAccOut)
 	concreteAccOut, err = DecodeConcrete([]byte("flungepliffery munknut tolopops"))
 	assert.Error(t, err)
diff --git a/account/bytecode.go b/account/bytecode.go
index f0f8b9a8aecededce4b7ab2b1d5cdcabed0bf6bd..01a1cdaddb15ca3e6cba73b06221949507a0d449 100644
--- a/account/bytecode.go
+++ b/account/bytecode.go
@@ -75,8 +75,8 @@ func (bc Bytecode) Tokens() ([]string, error) {
 			return tokens, fmt.Errorf("did not recognise byte %#x at position %v as an OpCode:\n %s",
 				bc[i], i, lexingPositionString(bc, i, tokens))
 		}
-		tokens = append(tokens, op.Name())
 		pushes := op.Pushes()
+		tokens = append(tokens, op.Name())
 		if pushes > 0 {
 			// This is a PUSH<N> OpCode so consume N bytes from the input, render them as hex, and skip to next OpCode
 			if i+pushes >= len(bc) {
diff --git a/account/private_account.go b/account/private_account.go
index 59f8245f109f7aed6a2847ee9808af27e50d85a4..9b705a02d518ede77b9047bc4288473259fff961 100644
--- a/account/private_account.go
+++ b/account/private_account.go
@@ -68,6 +68,10 @@ func (cpaw concretePrivateAccountWrapper) PrivateKey() PrivateKey {
 	return cpaw.ConcretePrivateAccount.PrivateKey
 }
 
+func (cpaw concretePrivateAccountWrapper) String() string {
+	return cpaw.ConcretePrivateAccount.String()
+}
+
 // ConcretePrivateAccount
 
 func (pa ConcretePrivateAccount) PrivateAccount() PrivateAccount {
diff --git a/account/state.go b/account/state.go
deleted file mode 100644
index 5569fbe636afc94f665f40970fe6267d5a7dac58..0000000000000000000000000000000000000000
--- a/account/state.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package account
-
-import (
-	"github.com/hyperledger/burrow/binary"
-)
-
-type Getter interface {
-	// Get an account by its address return nil if it does not exist (which should not be an error)
-	GetAccount(address Address) (Account, error)
-}
-
-type Iterable interface {
-	// Iterates through accounts calling passed function once per account, if the consumer
-	// returns true the iteration breaks and returns true to indicate it iteration
-	// was escaped
-	IterateAccounts(consumer func(Account) (stop bool)) (stopped bool, err error)
-}
-
-type Updater interface {
-	// Updates the fields of updatedAccount by address, creating the account
-	// if it does not exist
-	UpdateAccount(updatedAccount Account) error
-	// Remove the account at address
-	RemoveAccount(address Address) error
-}
-
-type StorageGetter interface {
-	// Retrieve a 32-byte value stored at key for the account at address, return Zero256 if key does not exist but
-	// error if address does not
-	GetStorage(address Address, key binary.Word256) (value binary.Word256, err error)
-}
-
-type StorageSetter interface {
-	// Store a 32-byte value at key for the account at address
-	SetStorage(address Address, key, value binary.Word256) error
-}
-
-type StorageIterable interface {
-	// Iterates through the storage of account ad address calling the passed function once per account,
-	// if the iterator function returns true the iteration breaks and returns true to indicate it iteration
-	// was escaped
-	IterateStorage(address Address, consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error)
-}
-
-// Compositions
-
-// Read-only account and storage state
-type StateReader interface {
-	Getter
-	StorageGetter
-}
-
-// Read and list account and storage state
-type StateIterable interface {
-	StateReader
-	Iterable
-	StorageIterable
-}
-
-// Read and write account and storage state
-type StateWriter interface {
-	StateReader
-	Updater
-	StorageSetter
-}
-
-type IterableStateWriter interface {
-	StateReader
-	Updater
-	StorageSetter
-	Iterable
-	StorageIterable
-}
diff --git a/account/state/state.go b/account/state/state.go
new file mode 100644
index 0000000000000000000000000000000000000000..005d3082132303bbdb23db5cab678fe85528d077
--- /dev/null
+++ b/account/state/state.go
@@ -0,0 +1,101 @@
+package state
+
+import (
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+	ptypes "github.com/hyperledger/burrow/permission/types"
+)
+
+type AccountGetter interface {
+	// Get an account by its address return nil if it does not exist (which should not be an error)
+	GetAccount(address acm.Address) (acm.Account, error)
+}
+
+type AccountIterable interface {
+	// Iterates through accounts calling passed function once per account, if the consumer
+	// returns true the iteration breaks and returns true to indicate it iteration
+	// was escaped
+	IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error)
+}
+
+type AccountUpdater interface {
+	// Updates the fields of updatedAccount by address, creating the account
+	// if it does not exist
+	UpdateAccount(updatedAccount acm.Account) error
+	// Remove the account at address
+	RemoveAccount(address acm.Address) error
+}
+
+type StorageGetter interface {
+	// Retrieve a 32-byte value stored at key for the account at address, return Zero256 if key does not exist but
+	// error if address does not
+	GetStorage(address acm.Address, key binary.Word256) (value binary.Word256, err error)
+}
+
+type StorageSetter interface {
+	// Store a 32-byte value at key for the account at address
+	SetStorage(address acm.Address, key, value binary.Word256) error
+}
+
+type StorageIterable interface {
+	// Iterates through the storage of account ad address calling the passed function once per account,
+	// if the iterator function returns true the iteration breaks and returns true to indicate it iteration
+	// was escaped
+	IterateStorage(address acm.Address, consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error)
+}
+
+// Compositions
+
+// Read-only account and storage state
+type Reader interface {
+	AccountGetter
+	StorageGetter
+}
+
+// Read and list account and storage state
+type Iterable interface {
+	Reader
+	AccountIterable
+	StorageIterable
+}
+
+// Read and write account and storage state
+type Writer interface {
+	Reader
+	AccountUpdater
+	StorageSetter
+}
+
+type IterableWriter interface {
+	Reader
+	AccountUpdater
+	StorageSetter
+	AccountIterable
+	StorageIterable
+}
+
+func GetMutableAccount(getter AccountGetter, address acm.Address) (acm.MutableAccount, error) {
+	acc, err := getter.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	return acm.AsMutableAccount(acc), nil
+}
+
+func GlobalPermissionsAccount(getter AccountGetter) acm.Account {
+	acc, err := getter.GetAccount(acm.GlobalPermissionsAddress)
+	if err != nil {
+		panic("Could not get global permission account, but this must exist")
+	}
+	return acc
+}
+
+// Get global permissions from the account at GlobalPermissionsAddress
+func GlobalAccountPermissions(getter AccountGetter) ptypes.AccountPermissions {
+	if getter == nil {
+		return ptypes.AccountPermissions{
+			Roles: []string{},
+		}
+	}
+	return GlobalPermissionsAccount(getter).Permissions()
+}
diff --git a/account/state_cache.go b/account/state/state_cache.go
similarity index 76%
rename from account/state_cache.go
rename to account/state/state_cache.go
index 28b6d0c58affd8a2f3383847459985b0ebd2a241..f9d85c979c2e253a6d417f49338d3579894663f6 100644
--- a/account/state_cache.go
+++ b/account/state/state_cache.go
@@ -12,48 +12,49 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package account
+package state
 
 import (
 	"fmt"
 	"sort"
 	"sync"
 
+	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/binary"
 )
 
-type StateCache interface {
-	IterableStateWriter
-	Sync(state StateWriter) error
-	Reset(backend StateIterable)
-	Flush(state IterableStateWriter) error
-	Backend() StateIterable
+type Cache interface {
+	IterableWriter
+	Sync(state Writer) error
+	Reset(backend Iterable)
+	Flush(state IterableWriter) error
+	Backend() Iterable
 }
 
 type stateCache struct {
 	sync.RWMutex
-	backend  StateIterable
-	accounts map[Address]*accountInfo
+	backend  Iterable
+	accounts map[acm.Address]*accountInfo
 }
 
 type accountInfo struct {
 	sync.RWMutex
-	account Account
+	account acm.Account
 	storage map[binary.Word256]binary.Word256
 	removed bool
 	updated bool
 }
 
-// Returns a StateCache that wraps an underlying StateReader to use on a cache miss, can write to an output StateWriter
+// Returns a Cache that wraps an underlying Reader to use on a cache miss, can write to an output Writer
 // via Sync. Goroutine safe for concurrent access.
-func NewStateCache(backend StateIterable) StateCache {
+func NewCache(backend Iterable) Cache {
 	return &stateCache{
 		backend:  backend,
-		accounts: make(map[Address]*accountInfo),
+		accounts: make(map[acm.Address]*accountInfo),
 	}
 }
 
-func (cache *stateCache) GetAccount(address Address) (Account, error) {
+func (cache *stateCache) GetAccount(address acm.Address) (acm.Account, error) {
 	accInfo, err := cache.get(address)
 	if err != nil {
 		return nil, err
@@ -66,7 +67,7 @@ func (cache *stateCache) GetAccount(address Address) (Account, error) {
 	return accInfo.account, nil
 }
 
-func (cache *stateCache) UpdateAccount(account Account) error {
+func (cache *stateCache) UpdateAccount(account acm.Account) error {
 	accInfo, err := cache.get(account.Address())
 	if err != nil {
 		return err
@@ -78,10 +79,11 @@ func (cache *stateCache) UpdateAccount(account Account) error {
 	}
 	accInfo.account = account
 	accInfo.updated = true
+
 	return nil
 }
 
-func (cache *stateCache) RemoveAccount(address Address) error {
+func (cache *stateCache) RemoveAccount(address acm.Address) error {
 	accInfo, err := cache.get(address)
 	if err != nil {
 		return err
@@ -96,7 +98,7 @@ func (cache *stateCache) RemoveAccount(address Address) error {
 }
 
 // Iterates over all accounts first in cache and then in backend until consumer returns true for 'stop'
-func (cache *stateCache) IterateAccounts(consumer func(Account) (stop bool)) (stopped bool, err error) {
+func (cache *stateCache) IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error) {
 	// Try cache first for early exit
 	cache.RLock()
 	for _, info := range cache.accounts {
@@ -108,7 +110,7 @@ func (cache *stateCache) IterateAccounts(consumer func(Account) (stop bool)) (st
 	return cache.backend.IterateAccounts(consumer)
 }
 
-func (cache *stateCache) GetStorage(address Address, key binary.Word256) (binary.Word256, error) {
+func (cache *stateCache) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) {
 	accInfo, err := cache.get(address)
 	if err != nil {
 		return binary.Zero256, err
@@ -133,7 +135,7 @@ func (cache *stateCache) GetStorage(address Address, key binary.Word256) (binary
 }
 
 // NOTE: Set value to zero to remove.
-func (cache *stateCache) SetStorage(address Address, key binary.Word256, value binary.Word256) error {
+func (cache *stateCache) SetStorage(address acm.Address, key binary.Word256, value binary.Word256) error {
 	accInfo, err := cache.get(address)
 	accInfo.Lock()
 	defer accInfo.Unlock()
@@ -149,7 +151,7 @@ func (cache *stateCache) SetStorage(address Address, key binary.Word256, value b
 }
 
 // Iterates over all storage items first in cache and then in backend until consumer returns true for 'stop'
-func (cache *stateCache) IterateStorage(address Address,
+func (cache *stateCache) IterateStorage(address acm.Address,
 	consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error) {
 	accInfo, err := cache.get(address)
 	if err != nil {
@@ -168,10 +170,10 @@ func (cache *stateCache) IterateStorage(address Address,
 
 // Syncs changes to the backend in deterministic order. Sends storage updates before updating
 // the account they belong so that storage values can be taken account of in the update.
-func (cache *stateCache) Sync(state StateWriter) error {
+func (cache *stateCache) Sync(state Writer) error {
 	cache.Lock()
 	defer cache.Unlock()
-	var addresses Addresses
+	var addresses acm.Addresses
 	for address := range cache.accounts {
 		addresses = append(addresses, address)
 	}
@@ -212,15 +214,15 @@ func (cache *stateCache) Sync(state StateWriter) error {
 }
 
 // Resets the cache to empty initialising the backing map to the same size as the previous iteration.
-func (cache *stateCache) Reset(backend StateIterable) {
+func (cache *stateCache) Reset(backend Iterable) {
 	cache.Lock()
 	defer cache.Unlock()
 	cache.backend = backend
-	cache.accounts = make(map[Address]*accountInfo, len(cache.accounts))
+	cache.accounts = make(map[acm.Address]*accountInfo, len(cache.accounts))
 }
 
-// Syncs the StateCache and Resets it to use as the backend StateReader
-func (cache *stateCache) Flush(state IterableStateWriter) error {
+// Syncs the Cache and Resets it to use as the backend Reader
+func (cache *stateCache) Flush(state IterableWriter) error {
 	err := cache.Sync(state)
 	if err != nil {
 		return err
@@ -229,12 +231,12 @@ func (cache *stateCache) Flush(state IterableStateWriter) error {
 	return nil
 }
 
-func (cache *stateCache) Backend() StateIterable {
+func (cache *stateCache) Backend() Iterable {
 	return cache.backend
 }
 
 // Get the cache accountInfo item creating it if necessary
-func (cache *stateCache) get(address Address) (*accountInfo, error) {
+func (cache *stateCache) get(address acm.Address) (*accountInfo, error) {
 	cache.RLock()
 	accInfo := cache.accounts[address]
 	cache.RUnlock()
diff --git a/account/state/state_cache_test.go b/account/state/state_cache_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..de9683b2fbdc16f8ec93dc0577408b76431d04e5
--- /dev/null
+++ b/account/state/state_cache_test.go
@@ -0,0 +1,190 @@
+package state
+
+import (
+	"fmt"
+	"testing"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/execution/evm/asm"
+	"github.com/hyperledger/burrow/permission"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestStateCache_GetAccount(t *testing.T) {
+	// Build backend states for read and write
+	readBackend := testAccounts()
+	writeBackend := NewCache(newTestState())
+	cache := NewCache(readBackend)
+
+	acc := readBackend.Accounts[addressOf("acc1")]
+	accOut, err := cache.GetAccount(acc.Address())
+	require.NoError(t, err)
+	cache.UpdateAccount(accOut)
+	assert.Equal(t, acm.AsConcreteAccount(acc), acm.AsConcreteAccount(accOut))
+
+	err = cache.Sync(writeBackend)
+	require.NoError(t, err)
+	accOut, err = writeBackend.GetAccount(acc.Address())
+	require.NotNil(t, accOut)
+	assert.NoError(t, err)
+	assert.Equal(t, acm.AsConcreteAccount(acc), acm.AsConcreteAccount(accOut))
+}
+
+func TestStateCache_UpdateAccount(t *testing.T) {
+	// Build backend states for read and write
+	backend := NewCache(newTestState())
+	cache := NewCache(backend)
+	// Create acccount
+	accNew := acm.NewConcreteAccountFromSecret("accNew")
+	balance := uint64(24)
+	accNew.Balance = balance
+	err := cache.UpdateAccount(accNew.Account())
+	require.NoError(t, err)
+
+	// Check cache
+	accNewOut, err := cache.GetAccount(accNew.Address)
+	require.NoError(t, err)
+	assert.Equal(t, balance, accNewOut.Balance())
+
+	// Check not stored in backend
+	accNewOut, err = backend.GetAccount(accNew.Address)
+	require.NoError(t, err)
+	assert.Nil(t, accNewOut)
+
+	// Check syncs to backend
+	err = cache.Sync(backend)
+	require.NoError(t, err)
+	accNewOut, err = backend.GetAccount(accNew.Address)
+	require.NoError(t, err)
+	assert.Equal(t, balance, accNewOut.Balance())
+
+	// Alter in cache
+	newBalance := uint64(100029)
+	accNew.Balance = newBalance
+	err = cache.UpdateAccount(accNew.Account())
+	require.NoError(t, err)
+
+	// Check cache
+	accNewOut, err = cache.GetAccount(accNew.Address)
+	require.NoError(t, err)
+	assert.Equal(t, newBalance, accNewOut.Balance())
+
+	// Check backend unchanged
+	accNewOut, err = backend.GetAccount(accNew.Address)
+	require.NoError(t, err)
+	assert.Equal(t, balance, accNewOut.Balance())
+}
+
+func TestStateCache_RemoveAccount(t *testing.T) {
+}
+
+func TestStateCache_GetStorage(t *testing.T) {
+}
+
+func TestStateCache_SetStorage(t *testing.T) {
+}
+
+func TestStateCache_Sync(t *testing.T) {
+}
+
+func TestStateCache_get(t *testing.T) {
+}
+
+func testAccounts() *testState {
+	acc1 := acm.NewConcreteAccountFromSecret("acc1")
+	acc1.Permissions.Base.Perms = permission.AddRole | permission.Send
+	acc1.Permissions.Base.SetBit = acc1.Permissions.Base.Perms
+
+	acc2 := acm.NewConcreteAccountFromSecret("acc2")
+	acc2.Permissions.Base.Perms = permission.AddRole | permission.Send
+	acc2.Permissions.Base.SetBit = acc1.Permissions.Base.Perms
+	acc2.Code, _ = acm.NewBytecode(asm.PUSH1, 0x20)
+
+	cache := combine(
+		account(acc1.Account(), "I AM A KEY", "NO YOU ARE A KEY"),
+		account(acc2.Account(), "ducks", "have lucks",
+			"chickens", "just cluck"),
+	)
+	return cache
+}
+
+func addressOf(secret string) acm.Address {
+	return acm.NewConcreteAccountFromSecret(secret).Address
+}
+
+// testState StateIterable
+
+type testState struct {
+	Accounts map[acm.Address]acm.Account
+	Storage  map[acm.Address]map[binary.Word256]binary.Word256
+}
+
+var _ Iterable = &testState{}
+
+func newTestState() *testState {
+	return &testState{
+		Accounts: make(map[acm.Address]acm.Account),
+		Storage:  make(map[acm.Address]map[binary.Word256]binary.Word256),
+	}
+}
+
+func account(acc acm.Account, keyvals ...string) *testState {
+	ts := newTestState()
+	ts.Accounts[acc.Address()] = acc
+	ts.Storage[acc.Address()] = make(map[binary.Word256]binary.Word256)
+	for i := 0; i < len(keyvals); i += 2 {
+		ts.Storage[acc.Address()][word(keyvals[i])] = word(keyvals[i+1])
+	}
+	return ts
+}
+
+func combine(states ...*testState) *testState {
+	ts := newTestState()
+	for _, state := range states {
+		for _, acc := range state.Accounts {
+			ts.Accounts[acc.Address()] = acc
+			ts.Storage[acc.Address()] = state.Storage[acc.Address()]
+		}
+	}
+	return ts
+}
+
+func word(str string) binary.Word256 {
+	return binary.LeftPadWord256([]byte(str))
+}
+
+func (tsr *testState) IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error) {
+	for _, acc := range tsr.Accounts {
+		if consumer(acc) {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+func (tsr *testState) IterateStorage(address acm.Address, consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error) {
+	for key, value := range tsr.Storage[address] {
+		if consumer(key, value) {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+func (tsr *testState) GetAccount(address acm.Address) (acm.Account, error) {
+	return tsr.Accounts[address], nil
+}
+
+func (tsr *testState) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) {
+	storage, ok := tsr.Storage[address]
+	if !ok {
+		return binary.Zero256, fmt.Errorf("could not find storage for account %s", address)
+	}
+	value, ok := storage[key]
+	if !ok {
+		return binary.Zero256, fmt.Errorf("could not find key %x for account %s", key, address)
+	}
+	return value, nil
+}
diff --git a/account/state_cache_test.go b/account/state_cache_test.go
deleted file mode 100644
index 6ecc2cdd108b2e947b567943afdcf4ccdf40565d..0000000000000000000000000000000000000000
--- a/account/state_cache_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package account
-
-import (
-	"testing"
-
-	"fmt"
-
-	"github.com/hyperledger/burrow/binary"
-)
-
-// TODO: write tests as part of feature branch
-type testStateReader struct {
-	Accounts map[Address]Account
-	Storage  map[Address]map[binary.Word256]binary.Word256
-}
-
-func accountAndStorage(account Account, keyvals ...binary.Word256) *testStateReader {
-	return &testStateReader{}
-
-}
-
-func (tsr *testStateReader) GetAccount(address Address) (Account, error) {
-	account, ok := tsr.Accounts[address]
-	if !ok {
-		return nil, fmt.Errorf("could not find account %s", address)
-	}
-	return account, nil
-}
-
-func (tsr *testStateReader) GetStorage(address Address, key binary.Word256) (binary.Word256, error) {
-	storage, ok := tsr.Storage[address]
-	if !ok {
-		return binary.Zero256, fmt.Errorf("could not find storage for account %s", address)
-	}
-	value, ok := storage[key]
-	if !ok {
-		return binary.Zero256, fmt.Errorf("could not find key %x for account %s", key, address)
-	}
-	return value, nil
-}
-
-var _ StateReader = &testStateReader{}
-
-func TestStateCache_GetAccount(t *testing.T) {
-}
-
-func TestStateCache_UpdateAccount(t *testing.T) {
-}
-
-func TestStateCache_RemoveAccount(t *testing.T) {
-}
-
-func TestStateCache_GetStorage(t *testing.T) {
-}
-
-func TestStateCache_SetStorage(t *testing.T) {
-}
-
-func TestStateCache_Sync(t *testing.T) {
-}
-
-func TestStateCache_get(t *testing.T) {
-}
diff --git a/binary/word256.go b/binary/word256.go
index 7bdbb4ec0e63921e44ff8b3191b2485aa3a8cb6f..b24f869cafcc0aff5baf976504d43ba54603309c 100644
--- a/binary/word256.go
+++ b/binary/word256.go
@@ -108,6 +108,7 @@ func Uint64FromWord256(word Word256) uint64 {
 }
 
 func Int64FromWord256(word Word256) int64 {
+
 	buf := word.Postfix(8)
 	return GetInt64BE(buf)
 }
diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go
index 6cda8da59ce02519dabb8159ad03a9b1310eac86..dae49f81adc865be17b0c5f4d9d6fc1a9dee0975 100644
--- a/blockchain/blockchain.go
+++ b/blockchain/blockchain.go
@@ -24,7 +24,6 @@ import (
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	dbm "github.com/tendermint/tmlibs/db"
 )
 
@@ -99,10 +98,10 @@ type PersistedState struct {
 }
 
 func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc,
-	logger logging_types.InfoTraceLogger) (*blockchain, error) {
+	logger *logging.Logger) (*blockchain, error) {
 
-	logger = logging.WithScope(logger, "LoadOrNewBlockchain")
-	logging.InfoMsg(logger, "Trying to load blockchain state from database",
+	logger = logger.WithScope("LoadOrNewBlockchain")
+	logger.InfoMsg("Trying to load blockchain state from database",
 		"database_key", stateKey)
 	blockchain, err := LoadBlockchain(db)
 	if err != nil {
@@ -118,7 +117,7 @@ func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc,
 		return blockchain, nil
 	}
 
-	logging.InfoMsg(logger, "No existing blockchain state found in database, making new blockchain")
+	logger.InfoMsg("No existing blockchain state found in database, making new blockchain")
 	return NewBlockchain(db, genesisDoc), nil
 }
 
diff --git a/client/methods/helpers.go b/client/methods/helpers.go
index 6cdb8b3aedaca504d7ec803c250f9e1265686e0a..6fbf1f46ebc2b2d3c863193f6c5312d4e270d777 100644
--- a/client/methods/helpers.go
+++ b/client/methods/helpers.go
@@ -20,10 +20,9 @@ import (
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/lifecycle"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 )
 
-func unpackSignAndBroadcast(result *rpc.TxResult, logger logging_types.InfoTraceLogger) {
+func unpackSignAndBroadcast(result *rpc.TxResult, logger *logging.Logger) {
 	if result == nil {
 		// if we don't provide --sign or --broadcast
 		return
@@ -42,15 +41,15 @@ func unpackSignAndBroadcast(result *rpc.TxResult, logger logging_types.InfoTrace
 		)
 	}
 
-	logging.InfoMsg(logger, "SignAndBroadcast result")
+	logger.InfoMsg("SignAndBroadcast result")
 }
 
-func loggerFromClientDo(do *client.Do, scope string) (logging_types.InfoTraceLogger, error) {
+func loggerFromClientDo(do *client.Do, scope string) (*logging.Logger, error) {
 	logger, err := lifecycle.NewLoggerFromLoggingConfig(config.DefaultClientLoggingConfig())
 	if err != nil {
 		return nil, err
 	}
-	logger = logging.WithScope(logger, scope)
+	logger = logger.WithScope(scope)
 	lifecycle.CaptureStdlibLogOutput(logger)
 	return logger, nil
 }
diff --git a/client/methods/status.go b/client/methods/status.go
index 14a8be609eb100ca2cdecc3652f6af840e45cd6d..7487fdf19bafecda67104aad6a7d4b871ec8f080 100644
--- a/client/methods/status.go
+++ b/client/methods/status.go
@@ -36,7 +36,7 @@ func Status(do *client.Do) error {
 		return fmt.Errorf("Error requesting chainId from chain at (%s): %s", do.NodeAddrFlag, err)
 	}
 
-	logger.Info("chain", do.NodeAddrFlag,
+	logger.Info.Log("chain", do.NodeAddrFlag,
 		"genesisHash", fmt.Sprintf("%X", genesisHash),
 		"chainName", chainName,
 		"chainId", chainId,
diff --git a/client/mock/client_mock.go b/client/mock/client_mock.go
index 5e195aefa2a679870b74b0876eb864257cace799..0fb53896ffb2284a7e9d754d75577afae03627b8 100644
--- a/client/mock/client_mock.go
+++ b/client/mock/client_mock.go
@@ -17,8 +17,7 @@ package mock
 import (
 	acm "github.com/hyperledger/burrow/account"
 	. "github.com/hyperledger/burrow/client"
-	"github.com/hyperledger/burrow/logging/loggers"
-	logging_types "github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/hyperledger/burrow/txs"
 	"github.com/tendermint/go-crypto"
@@ -100,6 +99,6 @@ func (mock *MockNodeClient) ListValidators() (blockHeight uint64, bondedValidato
 	return
 }
 
-func (mock *MockNodeClient) Logger() logging_types.InfoTraceLogger {
-	return loggers.NewNoopInfoTraceLogger()
+func (mock *MockNodeClient) Logger() *logging.Logger {
+	return logging.NewNoopLogger()
 }
diff --git a/client/node_client.go b/client/node_client.go
index aecfb847894e58657936c61ea40e8d65d31fd1bd..6e19231a2405c1edced4b45d713a968c61851a9c 100644
--- a/client/node_client.go
+++ b/client/node_client.go
@@ -19,7 +19,6 @@ import (
 
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/rpc"
 	tendermint_client "github.com/hyperledger/burrow/rpc/tm/client"
 	"github.com/hyperledger/burrow/txs"
@@ -41,7 +40,7 @@ type NodeClient interface {
 	ListValidators() (blockHeight uint64, bondedValidators, unbondingValidators []acm.Validator, err error)
 
 	// Logging context for this NodeClient
-	Logger() logging_types.InfoTraceLogger
+	Logger() *logging.Logger
 }
 
 type NodeWebsocketClient interface {
@@ -59,15 +58,15 @@ var _ NodeClient = (*burrowNodeClient)(nil)
 // burrow-client is a simple struct exposing the client rpc methods
 type burrowNodeClient struct {
 	broadcastRPC string
-	logger       logging_types.InfoTraceLogger
+	logger       *logging.Logger
 }
 
 // BurrowKeyClient.New returns a new monax-keys client for provided rpc location
 // Monax-keys connects over http request-responses
-func NewBurrowNodeClient(rpcString string, logger logging_types.InfoTraceLogger) *burrowNodeClient {
+func NewBurrowNodeClient(rpcString string, logger *logging.Logger) *burrowNodeClient {
 	return &burrowNodeClient{
 		broadcastRPC: rpcString,
-		logger:       logging.WithScope(logger, "BurrowNodeClient"),
+		logger:       logger.WithScope("BurrowNodeClient"),
 	}
 }
 
@@ -101,7 +100,7 @@ func (burrowNodeClient *burrowNodeClient) DeriveWebsocketClient() (nodeWsClient
 	// }
 	// wsAddr = "ws://" + wsAddr
 	wsAddr = nodeAddr
-	logging.TraceMsg(burrowNodeClient.logger, "Subscribing to websocket address",
+	burrowNodeClient.logger.TraceMsg("Subscribing to websocket address",
 		"websocket address", wsAddr,
 		"endpoint", "/websocket",
 	)
@@ -111,7 +110,7 @@ func (burrowNodeClient *burrowNodeClient) DeriveWebsocketClient() (nodeWsClient
 	}
 	derivedBurrowNodeWebsocketClient := &burrowNodeWebsocketClient{
 		tendermintWebsocket: wsClient,
-		logger:              logging.WithScope(burrowNodeClient.logger, "BurrowNodeWebsocketClient"),
+		logger:              burrowNodeClient.logger.WithScope("BurrowNodeWebsocketClient"),
 	}
 	return derivedBurrowNodeWebsocketClient, nil
 }
@@ -260,6 +259,6 @@ func (burrowNodeClient *burrowNodeClient) ListValidators() (blockHeight uint64,
 	return
 }
 
-func (burrowNodeClient *burrowNodeClient) Logger() logging_types.InfoTraceLogger {
+func (burrowNodeClient *burrowNodeClient) Logger() *logging.Logger {
 	return burrowNodeClient.logger
 }
diff --git a/client/rpc/client.go b/client/rpc/client.go
index 53d80dbcf582742f0bed89eb4def2cf4d10a1fdc..3a76948c2638df2e4589c5e5188dc8bf75635c7d 100644
--- a/client/rpc/client.go
+++ b/client/rpc/client.go
@@ -24,6 +24,7 @@ import (
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/client"
 	"github.com/hyperledger/burrow/keys"
+	"github.com/hyperledger/burrow/permission/snatives"
 	"github.com/hyperledger/burrow/txs"
 )
 
@@ -114,7 +115,7 @@ func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey,
 	if err != nil {
 		return nil, fmt.Errorf("could not convert action '%s' to PermFlag: %v", action, err)
 	}
-	permArgs := ptypes.PermArgs{
+	permArgs := snatives.PermArgs{
 		PermFlag: permFlag,
 	}
 
diff --git a/client/rpc/client_util.go b/client/rpc/client_util.go
index d437a92dae88ef47846e443ecffc93f273f019cf..914ba28f6387d87305d11c694c9f96c416092253 100644
--- a/client/rpc/client_util.go
+++ b/client/rpc/client_util.go
@@ -22,7 +22,6 @@ import (
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/client"
 	"github.com/hyperledger/burrow/keys"
-	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/txs"
 )
 
@@ -89,7 +88,7 @@ func checkCommon(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey,
 		return
 	} else if pubkey != "" {
 		if addr != "" {
-			logging.InfoMsg(nodeClient.Logger(), "Both a public key and an address have been specified. The public key takes precedent.",
+			nodeClient.Logger().InfoMsg("Both a public key and an address have been specified. The public key takes precedent.",
 				"public_key", pubkey,
 				"address", addr,
 			)
@@ -141,7 +140,7 @@ func checkCommon(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey,
 			return pub, amt, sequence, err2
 		}
 		sequence = account.Sequence() + 1
-		logging.TraceMsg(nodeClient.Logger(), "Fetch sequence from node",
+		nodeClient.Logger().TraceMsg("Fetch sequence from node",
 			"sequence", sequence,
 			"account address", address,
 		)
diff --git a/client/websocket_client.go b/client/websocket_client.go
index 41ba931c3f689a2ba2a7af65631ae047d9b56f68..fe08dde89d912394e422cccd9e1f33f068f938a0 100644
--- a/client/websocket_client.go
+++ b/client/websocket_client.go
@@ -25,7 +25,6 @@ import (
 	exe_events "github.com/hyperledger/burrow/execution/events"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/rpc"
 	tm_client "github.com/hyperledger/burrow/rpc/tm/client"
 	"github.com/hyperledger/burrow/txs"
@@ -51,7 +50,7 @@ var _ NodeWebsocketClient = (*burrowNodeWebsocketClient)(nil)
 type burrowNodeWebsocketClient struct {
 	// TODO: assert no memory leak on closing with open websocket
 	tendermintWebsocket *rpcclient.WSClient
-	logger              logging_types.InfoTraceLogger
+	logger              *logging.Logger
 }
 
 // Subscribe to an eventid
@@ -107,7 +106,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation(
 
 			case response := <-burrowNodeWebsocketClient.tendermintWebsocket.ResponsesCh:
 				if response.Error != nil {
-					logging.InfoMsg(burrowNodeWebsocketClient.logger,
+					burrowNodeWebsocketClient.logger.InfoMsg(
 						"Error received on websocket channel", structure.ErrorKey, err)
 					continue
 				}
@@ -117,12 +116,12 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation(
 					resultSubscribe := new(rpc.ResultSubscribe)
 					err = json.Unmarshal(response.Result, resultSubscribe)
 					if err != nil {
-						logging.InfoMsg(burrowNodeWebsocketClient.logger, "Unable to unmarshal ResultSubscribe",
+						burrowNodeWebsocketClient.logger.InfoMsg("Unable to unmarshal ResultSubscribe",
 							structure.ErrorKey, err)
 						continue
 					}
 					// TODO: collect subscription IDs, push into channel and on completion
-					logging.InfoMsg(burrowNodeWebsocketClient.logger, "Received confirmation for event",
+					burrowNodeWebsocketClient.logger.InfoMsg("Received confirmation for event",
 						"event", resultSubscribe.EventID,
 						"subscription_id", resultSubscribe.SubscriptionID)
 
@@ -130,14 +129,14 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation(
 					resultEvent := new(rpc.ResultEvent)
 					err = json.Unmarshal(response.Result, resultEvent)
 					if err != nil {
-						logging.InfoMsg(burrowNodeWebsocketClient.logger, "Unable to unmarshal ResultEvent",
+						burrowNodeWebsocketClient.logger.InfoMsg("Unable to unmarshal ResultEvent",
 							structure.ErrorKey, err)
 						continue
 					}
 					blockData := resultEvent.EventDataNewBlock()
 					if blockData != nil {
 						latestBlockHash = blockData.Block.Hash()
-						logging.TraceMsg(burrowNodeWebsocketClient.logger, "Registered new block",
+						burrowNodeWebsocketClient.logger.TraceMsg("Registered new block",
 							"block", blockData.Block,
 							"latest_block_hash", latestBlockHash,
 						)
@@ -147,7 +146,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation(
 					resultEvent := new(rpc.ResultEvent)
 					err = json.Unmarshal(response.Result, resultEvent)
 					if err != nil {
-						logging.InfoMsg(burrowNodeWebsocketClient.logger, "Unable to unmarshal ResultEvent",
+						burrowNodeWebsocketClient.logger.InfoMsg("Unable to unmarshal ResultEvent",
 							structure.ErrorKey, err)
 						continue
 					}
@@ -165,7 +164,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation(
 					}
 
 					if !bytes.Equal(eventDataTx.Tx.Hash(chainId), tx.Hash(chainId)) {
-						logging.TraceMsg(burrowNodeWebsocketClient.logger, "Received different event",
+						burrowNodeWebsocketClient.logger.TraceMsg("Received different event",
 							// TODO: consider re-implementing TxID again, or other more clear debug
 							"received transaction event", eventDataTx.Tx.Hash(chainId))
 						continue
@@ -191,7 +190,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation(
 					return
 
 				default:
-					logging.InfoMsg(burrowNodeWebsocketClient.logger, "Received unsolicited response",
+					burrowNodeWebsocketClient.logger.InfoMsg("Received unsolicited response",
 						"response_id", response.ID,
 						"expected_response_id", tm_client.EventResponseID(eventID))
 				}
diff --git a/cmd/burrow/main.go b/cmd/burrow/main.go
index 146a5d64a4adbc6f0542f5399679050e212fbdab..61c270aee1928791df6b64e372978520844ef1ad 100644
--- a/cmd/burrow/main.go
+++ b/cmd/burrow/main.go
@@ -8,12 +8,13 @@ import (
 
 	"github.com/hyperledger/burrow/config"
 	"github.com/hyperledger/burrow/config/source"
+	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/genesis/spec"
 	"github.com/hyperledger/burrow/keys"
+	"github.com/hyperledger/burrow/logging"
 	logging_config "github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/config/presets"
-	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/project"
 	"github.com/jawher/mow.cli"
 )
@@ -33,7 +34,7 @@ func main() {
 
 	burrow.Action = func() {
 		if *versionOpt {
-			fmt.Println(project.History.CurrentVersion().String())
+			fmt.Println(project.FullVersion())
 			os.Exit(0)
 		}
 		// We need to reflect on whether this obscures where values are coming from
@@ -137,8 +138,13 @@ func main() {
 			describeLoggingOpt := cmd.BoolOpt("describe-logging", false,
 				"Print an exhaustive list of logging instructions available with the --logging option")
 
+			debugOpt := cmd.BoolOpt("d debug", false, "Include maximal debug options in config "+
+				"including logging opcodes and dumping EVM tokens to disk these can be later pruned from the "+
+				"generated config.")
+
 			cmd.Spec = "[--keys-url=<keys URL>] [--genesis-spec=<GenesisSpec file> | --genesis-doc=<GenesisDoc file>] " +
-				"[--validator-index=<index>] [--toml-in] [--json-out] [--logging=<logging program>] [--describe-logging]"
+				"[--validator-index=<index>] [--toml-in] [--json-out] [--logging=<logging program>] " +
+				"[--describe-logging] [--debug]"
 
 			cmd.Action = func() {
 				conf := config.DefaultBurrowConfig()
@@ -172,7 +178,7 @@ func main() {
 					if err != nil {
 						fatalf("could not read GenesisSpec: %v", err)
 					}
-					keyClient := keys.NewKeyClient(conf.Keys.URL, loggers.NewNoopInfoTraceLogger())
+					keyClient := keys.NewKeyClient(conf.Keys.URL, logging.NewNoopLogger())
 					conf.GenesisDoc, err = genesisSpec.GenesisDoc(keyClient)
 					if err != nil {
 						fatalf("could not realise GenesisSpec: %v", err)
@@ -213,6 +219,12 @@ func main() {
 					}
 				}
 
+				if *debugOpt {
+					conf.Execution = &execution.ExecutionConfig{
+						VMOptions: []execution.VMOption{execution.DumpTokens, execution.DebugOpcodes},
+					}
+				}
+
 				if *jsonOutOpt {
 					os.Stdout.WriteString(conf.JSONString())
 				} else {
diff --git a/config/config.go b/config/config.go
index 91c5331b490be27c398e9e8ce528a894092d63a7..160f240632db14485053c0f20a91a77f3678e97e 100644
--- a/config/config.go
+++ b/config/config.go
@@ -10,6 +10,7 @@ import (
 	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/consensus/tendermint/validator"
 	"github.com/hyperledger/burrow/core"
+	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/keys"
 	logging_config "github.com/hyperledger/burrow/logging/config"
@@ -25,6 +26,7 @@ type BurrowConfig struct {
 	ValidatorAddress *acm.Address                       `json:",omitempty" toml:",omitempty"`
 	GenesisDoc       *genesis.GenesisDoc                `json:",omitempty" toml:",omitempty"`
 	Tendermint       *tendermint.BurrowTendermintConfig `json:",omitempty" toml:",omitempty"`
+	Execution        *execution.ExecutionConfig         `json:",omitempty" toml:",omitempty"`
 	Keys             *keys.KeysConfig                   `json:",omitempty" toml:",omitempty"`
 	RPC              *rpc.RPCConfig                     `json:",omitempty" toml:",omitempty"`
 	Logging          *logging_config.LoggingConfig      `json:",omitempty" toml:",omitempty"`
@@ -57,7 +59,17 @@ func (conf *BurrowConfig) Kernel(ctx context.Context) (*core.Kernel, error) {
 	}
 	privValidator := validator.NewPrivValidatorMemory(val, keys.Signer(keyClient, val.Address()))
 
-	return core.NewKernel(ctx, privValidator, conf.GenesisDoc, conf.Tendermint.TendermintConfig(), conf.RPC, logger)
+	var exeOptions []execution.ExecutionOption
+	if conf.Execution != nil {
+		var err error
+		exeOptions, err = conf.Execution.ExecutionOptions()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return core.NewKernel(ctx, privValidator, conf.GenesisDoc, conf.Tendermint.TendermintConfig(), conf.RPC, exeOptions,
+		logger)
 }
 
 func (conf *BurrowConfig) JSONString() string {
diff --git a/consensus/tendermint/abci/app.go b/consensus/tendermint/abci/app.go
index ee549575566b2420d0f53214d94f97d6a3ce63c5..1bc0700c3cafbd9a214cbe42350c812fcdd66391 100644
--- a/consensus/tendermint/abci/app.go
+++ b/consensus/tendermint/abci/app.go
@@ -10,7 +10,6 @@ import (
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/project"
 	"github.com/hyperledger/burrow/txs"
 	abci_types "github.com/tendermint/abci/types"
@@ -30,19 +29,19 @@ type abciApp struct {
 	// Utility
 	txDecoder txs.Decoder
 	// Logging
-	logger logging_types.InfoTraceLogger
+	logger *logging.Logger
 }
 
 func NewApp(blockchain bcm.MutableBlockchain,
 	checker execution.BatchExecutor,
 	committer execution.BatchCommitter,
-	logger logging_types.InfoTraceLogger) abci_types.Application {
+	logger *logging.Logger) abci_types.Application {
 	return &abciApp{
 		blockchain: blockchain,
 		checker:    checker,
 		committer:  committer,
 		txDecoder:  txs.NewGoWireCodec(),
-		logger:     logging.WithScope(logger.With(structure.ComponentKey, "ABCI_App"), "abci.NewApp"),
+		logger:     logger.WithScope("abci.NewApp").With(structure.ComponentKey, "ABCI_App"),
 	}
 }
 
@@ -73,7 +72,7 @@ func (app *abciApp) CheckTx(txBytes []byte) abci_types.ResponseCheckTx {
 	defer app.mtx.Unlock()
 	tx, err := app.txDecoder.DecodeTx(txBytes)
 	if err != nil {
-		logging.TraceMsg(app.logger, "CheckTx decoding error",
+		app.logger.TraceMsg("CheckTx decoding error",
 			"tag", "CheckTx",
 			structure.ErrorKey, err)
 		return abci_types.ResponseCheckTx{
@@ -86,7 +85,7 @@ func (app *abciApp) CheckTx(txBytes []byte) abci_types.ResponseCheckTx {
 
 	err = app.checker.Execute(tx)
 	if err != nil {
-		logging.TraceMsg(app.logger, "CheckTx execution error",
+		app.logger.TraceMsg("CheckTx execution error",
 			structure.ErrorKey, err,
 			"tag", "CheckTx",
 			"tx_hash", receipt.TxHash,
@@ -98,7 +97,7 @@ func (app *abciApp) CheckTx(txBytes []byte) abci_types.ResponseCheckTx {
 	}
 
 	receiptBytes := wire.BinaryBytes(receipt)
-	logging.TraceMsg(app.logger, "CheckTx success",
+	app.logger.TraceMsg("CheckTx success",
 		"tag", "CheckTx",
 		"tx_hash", receipt.TxHash,
 		"creates_contract", receipt.CreatesContract)
@@ -124,7 +123,7 @@ func (app *abciApp) DeliverTx(txBytes []byte) abci_types.ResponseDeliverTx {
 	defer app.mtx.Unlock()
 	tx, err := app.txDecoder.DecodeTx(txBytes)
 	if err != nil {
-		logging.TraceMsg(app.logger, "DeliverTx decoding error",
+		app.logger.TraceMsg("DeliverTx decoding error",
 			"tag", "DeliverTx",
 			structure.ErrorKey, err)
 		return abci_types.ResponseDeliverTx{
@@ -136,7 +135,7 @@ func (app *abciApp) DeliverTx(txBytes []byte) abci_types.ResponseDeliverTx {
 	receipt := txs.GenerateReceipt(app.blockchain.ChainID(), tx)
 	err = app.committer.Execute(tx)
 	if err != nil {
-		logging.TraceMsg(app.logger, "DeliverTx execution error",
+		app.logger.TraceMsg("DeliverTx execution error",
 			structure.ErrorKey, err,
 			"tag", "DeliverTx",
 			"tx_hash", receipt.TxHash,
@@ -147,7 +146,7 @@ func (app *abciApp) DeliverTx(txBytes []byte) abci_types.ResponseDeliverTx {
 		}
 	}
 
-	logging.TraceMsg(app.logger, "DeliverTx success",
+	app.logger.TraceMsg("DeliverTx success",
 		"tag", "DeliverTx",
 		"tx_hash", receipt.TxHash,
 		"creates_contract", receipt.CreatesContract)
@@ -168,7 +167,7 @@ func (app *abciApp) Commit() abci_types.ResponseCommit {
 	app.mtx.Lock()
 	defer app.mtx.Unlock()
 	tip := app.blockchain.Tip()
-	logging.InfoMsg(app.logger, "Committing block",
+	app.logger.InfoMsg("Committing block",
 		"tag", "Commit",
 		structure.ScopeKey, "Commit()",
 		"block_height", app.block.Header.Height,
@@ -204,7 +203,7 @@ func (app *abciApp) Commit() abci_types.ResponseCommit {
 
 	// Perform a sanity check our block height
 	if app.blockchain.LastBlockHeight() != uint64(app.block.Header.Height) {
-		logging.InfoMsg(app.logger, "Burrow block height disagrees with Tendermint block height",
+		app.logger.InfoMsg("Burrow block height disagrees with Tendermint block height",
 			structure.ScopeKey, "Commit()",
 			"burrow_height", app.blockchain.LastBlockHeight(),
 			"tendermint_height", app.block.Header.Height)
diff --git a/consensus/tendermint/logger.go b/consensus/tendermint/logger.go
index c42f46a4ca679890b6f67c5fd3f3978949bf0f8e..6022f47307eade096ddbd9e92c492cda12c9ae85 100644
--- a/consensus/tendermint/logger.go
+++ b/consensus/tendermint/logger.go
@@ -2,30 +2,29 @@ package tendermint
 
 import (
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/tendermint/tmlibs/log"
 )
 
 type tendermintLogger struct {
-	logger logging_types.InfoTraceLogger
+	logger *logging.Logger
 }
 
-func NewLogger(logger logging_types.InfoTraceLogger) *tendermintLogger {
+func NewLogger(logger *logging.Logger) *tendermintLogger {
 	return &tendermintLogger{
 		logger: logger,
 	}
 }
 
 func (tml *tendermintLogger) Info(msg string, keyvals ...interface{}) {
-	logging.InfoMsg(tml.logger, msg, keyvals...)
+	tml.logger.InfoMsg(msg, keyvals...)
 }
 
 func (tml *tendermintLogger) Error(msg string, keyvals ...interface{}) {
-	logging.InfoMsg(tml.logger, msg, keyvals...)
+	tml.logger.InfoMsg(msg, keyvals...)
 }
 
 func (tml *tendermintLogger) Debug(msg string, keyvals ...interface{}) {
-	logging.TraceMsg(tml.logger, msg, keyvals...)
+	tml.logger.TraceMsg(msg, keyvals...)
 }
 
 func (tml *tendermintLogger) With(keyvals ...interface{}) log.Logger {
diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go
index 7a3af288ad8149f76052c1cabbb4ce467e2763c5..27fa18ee4cdcf59e5589edfd7b86c99cae68d627 100644
--- a/consensus/tendermint/tendermint.go
+++ b/consensus/tendermint/tendermint.go
@@ -10,8 +10,8 @@ import (
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/txs"
 	abci_types "github.com/tendermint/abci/types"
 	"github.com/tendermint/tendermint/config"
@@ -49,7 +49,7 @@ func NewNode(
 	blockchain bcm.MutableBlockchain,
 	checker execution.BatchExecutor,
 	committer execution.BatchCommitter,
-	logger logging_types.InfoTraceLogger) (*Node, error) {
+	logger *logging.Logger) (*Node, error) {
 
 	var err error
 	// disable Tendermint's RPC
diff --git a/core/kernel.go b/core/kernel.go
index f00cd7a9b17d0d03f690ddcd2c135a6c33b63795..c033098e393abbc52dc8254e7acb6a652863f2eb 100644
--- a/core/kernel.go
+++ b/core/kernel.go
@@ -17,12 +17,15 @@ package core
 import (
 	"context"
 	"fmt"
+	"net/http"
+	_ "net/http/pprof"
 	"os"
 	"os/signal"
 	"sync"
 	"syscall"
 	"time"
 
+	kitlog "github.com/go-kit/kit/log"
 	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/consensus/tendermint/query"
@@ -31,7 +34,6 @@ import (
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/process"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/hyperledger/burrow/rpc/tm"
@@ -43,26 +45,31 @@ import (
 	dbm "github.com/tendermint/tmlibs/db"
 )
 
-const CooldownMilliseconds = 1000
-const ServerShutdownTimeoutMilliseconds = 1000
+const (
+	CooldownMilliseconds              = 1000
+	ServerShutdownTimeoutMilliseconds = 1000
+	LoggingCallerDepth                = 5
+)
 
 // Kernel is the root structure of Burrow
 type Kernel struct {
 	// Expose these public-facing interfaces to allow programmatic extension of the Kernel by other projects
 	Emitter        event.Emitter
-	Service        rpc.Service
+	Service        *rpc.Service
 	Launchers      []process.Launcher
-	Logger         logging_types.InfoTraceLogger
+	Logger         *logging.Logger
 	processes      map[string]process.Process
 	shutdownNotify chan struct{}
 	shutdownOnce   sync.Once
 }
 
 func NewKernel(ctx context.Context, privValidator tm_types.PrivValidator, genesisDoc *genesis.GenesisDoc,
-	tmConf *tm_config.Config, rpcConfig *rpc.RPCConfig, logger logging_types.InfoTraceLogger) (*Kernel, error) {
+	tmConf *tm_config.Config, rpcConfig *rpc.RPCConfig, exeOptions []execution.ExecutionOption,
+	logger *logging.Logger) (*Kernel, error) {
 
-	logger = logging.WithScope(logger, "NewKernel")
-	var err error
+	logger = logger.WithScope("NewKernel()").With(structure.TimeKey, kitlog.DefaultTimestampUTC)
+	tmLogger := logger.With(structure.CallerKey, kitlog.Caller(LoggingCallerDepth+1))
+	logger = logger.WithInfo(structure.CallerKey, kitlog.Caller(LoggingCallerDepth))
 	stateDB := dbm.NewDB("burrow_state", dbm.GoLevelDBBackendStr, tmConf.DBDir())
 
 	blockchain, err := bcm.LoadOrNewBlockchain(stateDB, genesisDoc, logger)
@@ -86,8 +93,8 @@ func NewKernel(ctx context.Context, privValidator tm_types.PrivValidator, genesi
 	checker := execution.NewBatchChecker(state, tmGenesisDoc.ChainID, blockchain, logger)
 
 	emitter := event.NewEmitter(logger)
-	committer := execution.NewBatchCommitter(state, tmGenesisDoc.ChainID, blockchain, emitter, logger)
-	tmNode, err := tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, blockchain, checker, committer, logger)
+	committer := execution.NewBatchCommitter(state, tmGenesisDoc.ChainID, blockchain, emitter, logger, exeOptions...)
+	tmNode, err := tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, blockchain, checker, committer, tmLogger)
 
 	if err != nil {
 		return nil, err
@@ -96,15 +103,25 @@ func NewKernel(ctx context.Context, privValidator tm_types.PrivValidator, genesi
 	transactor := execution.NewTransactor(blockchain, state, emitter, tendermint.BroadcastTxAsyncFunc(tmNode, txCodec),
 		logger)
 
-	// TODO: consider whether we need to be more explicit about pre-commit (check cache) versus committed (state) values
-	// Note we pass the checker as the StateIterable to NewService which means the RPC layers will query the check
-	// cache state. This is in line with previous behaviour of Burrow and chiefly serves to get provide a pre-commit
-	// view of sequence values on the node that a client is communicating with.
-	// Since we don't currently execute EVM code in the checker possible conflicts are limited to account creation
-	// which increments the creator's account Sequence and SendTxs
 	service := rpc.NewService(ctx, state, state, emitter, blockchain, transactor, query.NewNodeView(tmNode, txCodec), logger)
 
 	launchers := []process.Launcher{
+		{
+			Name:     "Profiling Server",
+			Disabled: rpcConfig.Profiler.Disabled,
+			Launch: func() (process.Process, error) {
+				debugServer := &http.Server{
+					Addr: ":6060",
+				}
+				go func() {
+					err := debugServer.ListenAndServe()
+					if err != nil {
+						logger.InfoMsg("Error from pprof debug server", structure.ErrorKey, err)
+					}
+				}()
+				return debugServer, nil
+			},
+		},
 		{
 			Name: "Database",
 			Launch: func() (process.Process, error) {
@@ -139,7 +156,7 @@ func NewKernel(ctx context.Context, privValidator tm_types.PrivValidator, genesi
 					case <-ctx.Done():
 						return ctx.Err()
 					case <-tmNode.Quit:
-						logging.InfoMsg(logger, "Tendermint Node has quit, closing DB connections...")
+						logger.InfoMsg("Tendermint Node has quit, closing DB connections...")
 						// Close tendermint database connections using our wrapper
 						tmNode.Close()
 						return nil
@@ -149,7 +166,8 @@ func NewKernel(ctx context.Context, privValidator tm_types.PrivValidator, genesi
 			},
 		},
 		{
-			Name: "RPC/tm",
+			Name:     "RPC/tm",
+			Disabled: rpcConfig.TM.Disabled,
 			Launch: func() (process.Process, error) {
 				listener, err := tm.StartServer(service, "/websocket", rpcConfig.TM.ListenAddress, emitter, logger)
 				if err != nil {
@@ -159,7 +177,8 @@ func NewKernel(ctx context.Context, privValidator tm_types.PrivValidator, genesi
 			},
 		},
 		{
-			Name: "RPC/V0",
+			Name:     "RPC/V0",
+			Disabled: rpcConfig.V0.Disabled,
 			Launch: func() (process.Process, error) {
 				codec := v0.NewTCodec()
 				jsonServer := v0.NewJSONServer(v0.NewJSONService(codec, service, logger))
@@ -216,7 +235,7 @@ func (kern *Kernel) supervise() {
 	signals := make(chan os.Signal, 1)
 	signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL)
 	sig := <-signals
-	logging.InfoMsg(kern.Logger, fmt.Sprintf("Caught %v signal so shutting down", sig),
+	kern.Logger.InfoMsg(fmt.Sprintf("Caught %v signal so shutting down", sig),
 		"signal", sig.String())
 	kern.Shutdown(context.Background())
 }
@@ -224,9 +243,9 @@ func (kern *Kernel) supervise() {
 // Stop the kernel allowing for a graceful shutdown of components in order
 func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
 	kern.shutdownOnce.Do(func() {
-		logger := logging.WithScope(kern.Logger, "Shutdown")
-		logging.InfoMsg(logger, "Attempting graceful shutdown...")
-		logging.InfoMsg(logger, "Shutting down servers")
+		logger := kern.Logger.WithScope("Shutdown")
+		logger.InfoMsg("Attempting graceful shutdown...")
+		logger.InfoMsg("Shutting down servers")
 		ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeoutMilliseconds*time.Millisecond)
 		defer cancel()
 		// Shutdown servers in reverse order to boot
@@ -234,10 +253,10 @@ func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
 			name := kern.Launchers[i].Name
 			srvr, ok := kern.processes[name]
 			if ok {
-				logging.InfoMsg(logger, "Shutting down server", "server_name", name)
+				logger.InfoMsg("Shutting down server", "server_name", name)
 				sErr := srvr.Shutdown(ctx)
 				if sErr != nil {
-					logging.InfoMsg(logger, "Failed to shutdown server",
+					logger.InfoMsg("Failed to shutdown server",
 						"server_name", name,
 						structure.ErrorKey, sErr)
 					if err == nil {
@@ -246,8 +265,9 @@ func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
 				}
 			}
 		}
-		logging.InfoMsg(logger, "Shutdown complete")
-		logging.Sync(kern.Logger)
+		logger.InfoMsg("Shutdown complete")
+		structure.Sync(kern.Logger.Info)
+		structure.Sync(kern.Logger.Trace)
 		// We don't want to wait for them, but yielding for a cooldown Let other goroutines flush
 		// potentially interesting final output (e.g. log messages)
 		time.Sleep(time.Millisecond * CooldownMilliseconds)
diff --git a/core/kernel_test.go b/core/kernel_test.go
index 427461075c7118fd5dde4c3364168fa4abe599f0..aa1af7efc1aefc498cef965014a6d163d6e7f5ab 100644
--- a/core/kernel_test.go
+++ b/core/kernel_test.go
@@ -12,8 +12,7 @@ import (
 	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/consensus/tendermint/validator"
 	"github.com/hyperledger/burrow/genesis"
-	"github.com/hyperledger/burrow/logging/loggers"
-	logging_types "github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/stretchr/testify/assert"
 	tm_config "github.com/tendermint/tendermint/config"
@@ -28,7 +27,7 @@ func TestBootThenShutdown(t *testing.T) {
 	os.Chdir(testDir)
 	tmConf := tm_config.DefaultConfig()
 	//logger, _, _ := lifecycle.NewStdErrLogger()
-	logger := loggers.NewNoopInfoTraceLogger()
+	logger := logging.NewNoopLogger()
 	genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
 	privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
 	assert.NoError(t, bootWaitBlocksShutdown(privValidator, genesisDoc, tmConf, logger, nil))
@@ -40,7 +39,7 @@ func TestBootShutdownResume(t *testing.T) {
 	os.Chdir(testDir)
 	tmConf := tm_config.DefaultConfig()
 	//logger, _, _ := lifecycle.NewStdErrLogger()
-	logger := loggers.NewNoopInfoTraceLogger()
+	logger := logging.NewNoopLogger()
 	genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
 	privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
 
@@ -62,10 +61,10 @@ func TestBootShutdownResume(t *testing.T) {
 }
 
 func bootWaitBlocksShutdown(privValidator tm_types.PrivValidator, genesisDoc *genesis.GenesisDoc,
-	tmConf *tm_config.Config, logger logging_types.InfoTraceLogger,
+	tmConf *tm_config.Config, logger *logging.Logger,
 	blockChecker func(block *tm_types.EventDataNewBlock) (cont bool)) error {
 
-	kern, err := NewKernel(context.Background(), privValidator, genesisDoc, tmConf, rpc.DefaultRPCConfig(), logger)
+	kern, err := NewKernel(context.Background(), privValidator, genesisDoc, tmConf, rpc.DefaultRPCConfig(), nil, logger)
 	if err != nil {
 		return err
 	}
diff --git a/event/cache_test.go b/event/cache_test.go
index 877d04387a2caef15ab0ba135181babf0a7cf44a..276d323c47ce444a505bfec63ef4d131fb0f2ef0 100644
--- a/event/cache_test.go
+++ b/event/cache_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -17,7 +17,7 @@ func TestEventCache_Flush(t *testing.T) {
 	errCh := make(chan error)
 	flushed := false
 
-	em := NewEmitter(loggers.NewNoopInfoTraceLogger())
+	em := NewEmitter(logging.NewNoopLogger())
 	SubscribeCallback(ctx, em, "nothingness", NewQueryBuilder(), func(message interface{}) bool {
 		// Check against sending a buffer of zeroed messages
 		if message == nil {
@@ -60,7 +60,7 @@ func TestEventCache_Flush(t *testing.T) {
 }
 
 func TestEventCacheGrowth(t *testing.T) {
-	evc := NewEventCache(NewEmitter(loggers.NewNoopInfoTraceLogger()))
+	evc := NewEventCache(NewEmitter(logging.NewNoopLogger()))
 
 	fireNEvents(evc, 100)
 	c := cap(evc.events)
diff --git a/event/convention_test.go b/event/convention_test.go
index 31e9571b148affcac0639cf02f8533c283c3d496..35c8f7d675cc2ddb870893b5545955e4d1b3d451 100644
--- a/event/convention_test.go
+++ b/event/convention_test.go
@@ -5,13 +5,13 @@ import (
 	"testing"
 	"time"
 
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestSubscribeCallback(t *testing.T) {
 	ctx := context.Background()
-	em := NewEmitter(loggers.NewNoopInfoTraceLogger())
+	em := NewEmitter(logging.NewNoopLogger())
 	ch := make(chan interface{})
 	SubscribeCallback(ctx, em, "TestSubscribeCallback", MatchAllQueryable(), func(msg interface{}) bool {
 		ch <- msg
diff --git a/event/emitter.go b/event/emitter.go
index d41d0fd1b30a4a798db16f000bd099f17fc17f81..a09d158f9fb830511a00a9fb15d5bbb395d72478 100644
--- a/event/emitter.go
+++ b/event/emitter.go
@@ -21,8 +21,8 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/process"
 	"github.com/tendermint/tmlibs/common"
 	"github.com/tendermint/tmlibs/pubsub"
@@ -52,10 +52,10 @@ type Emitter interface {
 type emitter struct {
 	common.BaseService
 	pubsubServer *pubsub.Server
-	logger       logging_types.InfoTraceLogger
+	logger       *logging.Logger
 }
 
-func NewEmitter(logger logging_types.InfoTraceLogger) Emitter {
+func NewEmitter(logger *logging.Logger) Emitter {
 	pubsubServer := pubsub.NewServer(pubsub.BufferCapacity(DefaultEventBufferCapacity))
 	pubsubServer.BaseService = *common.NewBaseService(nil, "Emitter", pubsubServer)
 	pubsubServer.Start()
diff --git a/event/emitter_test.go b/event/emitter_test.go
index 473bf4c5d5b8870a074257fb130cde1dab6ad218..c881cc53f3fede54cef50d2e913a25d158fe91a7 100644
--- a/event/emitter_test.go
+++ b/event/emitter_test.go
@@ -5,13 +5,13 @@ import (
 	"testing"
 	"time"
 
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
 func TestEmitter(t *testing.T) {
-	em := NewEmitter(loggers.NewNoopInfoTraceLogger())
+	em := NewEmitter(logging.NewNoopLogger())
 	ctx := context.Background()
 	out := make(chan interface{})
 
diff --git a/execution/config.go b/execution/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..f90b6a02c529fcd5aa67fee1abf1011f725673d2
--- /dev/null
+++ b/execution/config.go
@@ -0,0 +1,39 @@
+package execution
+
+import (
+	"fmt"
+
+	"github.com/hyperledger/burrow/execution/evm"
+)
+
+type VMOption string
+
+const (
+	DebugOpcodes VMOption = "DebugOpcodes"
+	DumpTokens   VMOption = "DumpTokens"
+)
+
+type ExecutionConfig struct {
+	VMOptions []VMOption `json:",omitempty" toml:",omitempty"`
+}
+
+func DefaultExecutionConfig() *ExecutionConfig {
+	return &ExecutionConfig{}
+}
+
+func (ec *ExecutionConfig) ExecutionOptions() ([]ExecutionOption, error) {
+	var exeOptions []ExecutionOption
+	var vmOptions []func(*evm.VM)
+	for _, option := range ec.VMOptions {
+		switch option {
+		case DebugOpcodes:
+			vmOptions = append(vmOptions, evm.DebugOpcodes)
+		case DumpTokens:
+			vmOptions = append(vmOptions, evm.DumpTokens)
+		default:
+			return nil, fmt.Errorf("VM option '%s' not recognised", option)
+		}
+	}
+	exeOptions = append(exeOptions, VMOptions(vmOptions...))
+	return exeOptions, nil
+}
diff --git a/execution/evm/accounts.go b/execution/evm/accounts.go
index 618557aaa9aabca3d6f4982ce81ad793f5838521..800e6269b1afb7f39c2fcf77a7e79722cc5d4147 100644
--- a/execution/evm/accounts.go
+++ b/execution/evm/accounts.go
@@ -3,17 +3,16 @@ package evm
 import (
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	ptypes "github.com/hyperledger/burrow/permission/types"
 )
 
 // Create a new account from a parent 'creator' account. The creator account will have its
 // sequence number incremented
 func DeriveNewAccount(creator acm.MutableAccount, permissions ptypes.AccountPermissions,
-	logger logging_types.InfoTraceLogger) acm.MutableAccount {
+	logger *logging.Logger) acm.MutableAccount {
 	// Generate an address
 	sequence := creator.Sequence()
-	logging.TraceMsg(logger, "Incrementing sequence number in DeriveNewAccount()",
+	logger.TraceMsg("Incrementing sequence number in DeriveNewAccount()",
 		"tag", "sequence",
 		"account", creator.Address(),
 		"old_sequence", sequence,
@@ -23,11 +22,11 @@ func DeriveNewAccount(creator acm.MutableAccount, permissions ptypes.AccountPerm
 	addr := acm.NewContractAddress(creator.Address(), sequence)
 
 	// Create account from address.
-	return (&acm.ConcreteAccount{
+	return acm.ConcreteAccount{
 		Address:     addr,
 		Balance:     0,
 		Code:        nil,
 		Sequence:    0,
 		Permissions: permissions,
-	}).MutableAccount()
+	}.MutableAccount()
 }
diff --git a/execution/evm/asm/opcodes.go b/execution/evm/asm/opcodes.go
index 0a4e353199718db0266c542e8e59b176704ca27e..0db53834facf9d6e682f06de1f58ccae99c321af 100644
--- a/execution/evm/asm/opcodes.go
+++ b/execution/evm/asm/opcodes.go
@@ -49,6 +49,9 @@ const (
 	XOR
 	NOT
 	BYTE
+	SHL
+	SHR
+	SAR
 
 	SHA3 = 0x20
 )
@@ -68,6 +71,8 @@ const (
 	GASPRICE_DEPRECATED
 	EXTCODESIZE
 	EXTCODECOPY
+	RETURNDATASIZE
+	RETURNDATACOPY
 )
 
 const (
@@ -182,6 +187,8 @@ const (
 	DELEGATECALL
 
 	// 0x70 range - other
+	STATICCALL   = 0xfa
+	REVERT       = 0xfd
 	SELFDESTRUCT = 0xff
 )
 
@@ -210,6 +217,9 @@ var opCodeNames = map[OpCode]string{
 	OR:     "OR",
 	XOR:    "XOR",
 	BYTE:   "BYTE",
+	SHL:    "SHL",
+	SHR:    "SHR",
+	SAR:    "SAR",
 	ADDMOD: "ADDMOD",
 	MULMOD: "MULMOD",
 
@@ -238,6 +248,8 @@ var opCodeNames = map[OpCode]string{
 	GASLIMIT:              "GASLIMIT",
 	EXTCODESIZE:           "EXTCODESIZE",
 	EXTCODECOPY:           "EXTCODECOPY",
+	RETURNDATASIZE:        "RETURNDATASIZE",
+	RETURNDATACOPY:        "RETURNDATACOPY",
 
 	// 0x50 range - 'storage' and execution
 	POP:      "POP",
@@ -332,8 +344,9 @@ var opCodeNames = map[OpCode]string{
 	RETURN:       "RETURN",
 	CALLCODE:     "CALLCODE",
 	DELEGATECALL: "DELEGATECALL",
-
+	STATICCALL:   "STATICCALL",
 	// 0x70 range - other
+	REVERT:       "REVERT",
 	SELFDESTRUCT: "SELFDESTRUCT",
 }
 
diff --git a/execution/evm/fake_app_state.go b/execution/evm/fake_app_state.go
index 09a985ca4efedc76265e3b829deb061441586b90..7efbe82cd9e13d90ca7fa21b57d381f47f781f39 100644
--- a/execution/evm/fake_app_state.go
+++ b/execution/evm/fake_app_state.go
@@ -20,6 +20,7 @@ import (
 	"bytes"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
 )
 
@@ -28,7 +29,7 @@ type FakeAppState struct {
 	storage  map[string]Word256
 }
 
-var _ acm.StateWriter = &FakeAppState{}
+var _ state.Writer = &FakeAppState{}
 
 func (fas *FakeAppState) GetAccount(addr acm.Address) (acm.Account, error) {
 	account := fas.accounts[addr]
diff --git a/execution/evm/gas.go b/execution/evm/gas.go
index a764a5a57f6985f20cda9dfc172c83ec27662afd..dff920c1586f01deb8144a1105f7ddb6532df830 100644
--- a/execution/evm/gas.go
+++ b/execution/evm/gas.go
@@ -18,6 +18,7 @@ const (
 	GasSha3          uint64 = 1
 	GasGetAccount    uint64 = 1
 	GasStorageUpdate uint64 = 1
+	GasCreateAccount uint64 = 1
 
 	GasBaseOp  uint64 = 0 // TODO: make this 1
 	GasStackOp uint64 = 1
diff --git a/execution/evm/log_event_test.go b/execution/evm/log_event_test.go
index 496e4e61068a9a7874fda6545b21623f3c224295..3a054d51afd1281da7c51ef66aab91a68425337a 100644
--- a/execution/evm/log_event_test.go
+++ b/execution/evm/log_event_test.go
@@ -26,7 +26,7 @@ import (
 	"github.com/hyperledger/burrow/event"
 	. "github.com/hyperledger/burrow/execution/evm/asm"
 	"github.com/hyperledger/burrow/execution/evm/events"
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/stretchr/testify/require"
 )
 
@@ -52,9 +52,9 @@ func TestLog4(t *testing.T) {
 	st.accounts[account1.Address()] = account1
 	st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(st, newParams(), acm.ZeroAddress, nil, logger)
 
-	emitter := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
+	emitter := event.NewEmitter(logging.NewNoopLogger())
 
 	ch := make(chan *events.EventDataLog)
 
diff --git a/execution/evm/native.go b/execution/evm/native.go
index 198977c4ccd3208c5522bd2d9aeaa8143665b0a0..70f00ed6d2a25c31a42de210f29161f0905cb68b 100644
--- a/execution/evm/native.go
+++ b/execution/evm/native.go
@@ -18,8 +18,9 @@ import (
 	"crypto/sha256"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
-	logging_types "github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/logging"
 	"golang.org/x/crypto/ripemd160"
 )
 
@@ -53,8 +54,8 @@ func registerNativeContracts() {
 
 //-----------------------------------------------------------------------------
 
-type NativeContract func(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error)
+type NativeContract func(state state.Writer, caller acm.Account, input []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error)
 
 /* Removed due to C dependency
 func ecrecoverFunc(state State, caller *acm.Account, input []byte, gas *int64) (output []byte, err error) {
@@ -73,14 +74,15 @@ func ecrecoverFunc(state State, caller *acm.Account, input []byte, gas *int64) (
 	recovered, err := secp256k1.RecoverPubkey(hash, sig)
 	if err != nil {
 		return nil, err
+OH NO STOCASTIC CAT CODING!!!!
 	}
 	hashed := sha3.Sha3(recovered[1:])
 	return LeftPadBytes(hashed, 32), nil
 }
 */
 
-func sha256Func(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func sha256Func(state state.Writer, caller acm.Account, input []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 	// Deduct gas
 	gasRequired := uint64((len(input)+31)/32)*GasSha256Word + GasSha256Base
 	if *gas < gasRequired {
@@ -95,8 +97,8 @@ func sha256Func(state acm.StateWriter, caller acm.Account, input []byte, gas *ui
 	return hasher.Sum(nil), nil
 }
 
-func ripemd160Func(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func ripemd160Func(state state.Writer, caller acm.Account, input []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 	// Deduct gas
 	gasRequired := uint64((len(input)+31)/32)*GasRipemd160Word + GasRipemd160Base
 	if *gas < gasRequired {
@@ -111,8 +113,8 @@ func ripemd160Func(state acm.StateWriter, caller acm.Account, input []byte, gas
 	return LeftPadBytes(hasher.Sum(nil), 32), nil
 }
 
-func identityFunc(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func identityFunc(state state.Writer, caller acm.Account, input []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 	// Deduct gas
 	gasRequired := uint64((len(input)+31)/32)*GasIdentityWord + GasIdentityBase
 	if *gas < gasRequired {
diff --git a/execution/evm/options.go b/execution/evm/options.go
new file mode 100644
index 0000000000000000000000000000000000000000..5081729daf98d75b1e5b46567451d9eb4578eb42
--- /dev/null
+++ b/execution/evm/options.go
@@ -0,0 +1,15 @@
+package evm
+
+func MemoryProvider(memoryProvider func() Memory) func(*VM) {
+	return func(vm *VM) {
+		vm.memoryProvider = memoryProvider
+	}
+}
+
+func DebugOpcodes(vm *VM) {
+	vm.debugOpcodes = true
+}
+
+func DumpTokens(vm *VM) {
+	vm.dumpTokens = true
+}
diff --git a/execution/evm/snative.go b/execution/evm/snative.go
index 4b8ac87cbed5c22a449d034070b256d05c4bb4bb..34375a0adf50b456ad74383a31f0936f0e1f223c 100644
--- a/execution/evm/snative.go
+++ b/execution/evm/snative.go
@@ -20,12 +20,12 @@ import (
 	"strings"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/execution/evm/abi"
 	"github.com/hyperledger/burrow/execution/evm/sha3"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/permission"
 	ptypes "github.com/hyperledger/burrow/permission/types"
 )
@@ -226,11 +226,20 @@ func NewSNativeContract(comment, name string,
 	}
 }
 
+type ErrLacksSNativePermission struct {
+	Address acm.Address
+	SNative string
+}
+
+func (e ErrLacksSNativePermission) Error() string {
+	return fmt.Sprintf("account %s does not have SNative function call permission: %s", e.Address, e.SNative)
+}
+
 // This function is designed to be called from the EVM once a SNative contract
 // has been selected. It is also placed in a registry by registerSNativeContracts
 // So it can be looked up by SNative address
-func (contract *SNativeContractDescription) Dispatch(state acm.StateWriter, caller acm.Account,
-	args []byte, gas *uint64, logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func (contract *SNativeContractDescription) Dispatch(state state.Writer, caller acm.Account,
+	args []byte, gas *uint64, logger *logging.Logger) (output []byte, err error) {
 
 	logger = logger.With(structure.ScopeKey, "Dispatch", "contract_name", contract.Name)
 
@@ -244,7 +253,7 @@ func (contract *SNativeContractDescription) Dispatch(state acm.StateWriter, call
 		return nil, err
 	}
 
-	logging.TraceMsg(logger, "Dispatching to function",
+	logger.TraceMsg("Dispatching to function",
 		"caller", caller.Address(),
 		"function_name", function.Name)
 
@@ -341,8 +350,8 @@ func abiReturn(name string, abiTypeName abi.TypeName) abi.Return {
 // Permission function defintions
 
 // TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
-func hasBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func hasBase(state state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	addrWord256, permNum := returnTwoArgs(args)
 	address := acm.AddressFromWord256(addrWord256)
@@ -359,7 +368,7 @@ func hasBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64
 	}
 	hasPermission := HasPermission(state, acc, permN)
 	permInt := byteFromBool(hasPermission)
-	logger.Trace("function", "hasBase",
+	logger.Trace.Log("function", "hasBase",
 		"address", address.String(),
 		"account_base_permissions", acc.Permissions().Base,
 		"perm_flag", fmt.Sprintf("%b", permN),
@@ -367,12 +376,12 @@ func hasBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func setBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func setBase(stateWriter state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	addrWord256, permNum, permVal := returnThreeArgs(args)
 	address := acm.AddressFromWord256(addrWord256)
-	acc, err := acm.GetMutableAccount(state, address)
+	acc, err := state.GetMutableAccount(stateWriter, address)
 	if err != nil {
 		return nil, err
 	}
@@ -387,19 +396,19 @@ func setBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64
 	if err = acc.MutablePermissions().Base.Set(permN, permV); err != nil {
 		return nil, err
 	}
-	state.UpdateAccount(acc)
-	logger.Trace("function", "setBase", "address", address.String(),
+	stateWriter.UpdateAccount(acc)
+	logger.Trace.Log("function", "setBase", "address", address.String(),
 		"permission_flag", fmt.Sprintf("%b", permN),
 		"permission_value", permV)
-	return effectivePermBytes(acc.Permissions().Base, globalPerms(state)), nil
+	return effectivePermBytes(acc.Permissions().Base, globalPerms(stateWriter)), nil
 }
 
-func unsetBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func unsetBase(stateWriter state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	addrWord256, permNum := returnTwoArgs(args)
 	address := acm.AddressFromWord256(addrWord256)
-	acc, err := acm.GetMutableAccount(state, address)
+	acc, err := state.GetMutableAccount(stateWriter, address)
 	if err != nil {
 		return nil, err
 	}
@@ -413,19 +422,19 @@ func unsetBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint
 	if err = acc.MutablePermissions().Base.Unset(permN); err != nil {
 		return nil, err
 	}
-	state.UpdateAccount(acc)
-	logger.Trace("function", "unsetBase", "address", address.String(),
+	stateWriter.UpdateAccount(acc)
+	logger.Trace.Log("function", "unsetBase", "address", address.String(),
 		"perm_flag", fmt.Sprintf("%b", permN),
 		"permission_flag", fmt.Sprintf("%b", permN))
 
-	return effectivePermBytes(acc.Permissions().Base, globalPerms(state)), nil
+	return effectivePermBytes(acc.Permissions().Base, globalPerms(stateWriter)), nil
 }
 
-func setGlobal(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func setGlobal(stateWriter state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	permNum, permVal := returnTwoArgs(args)
-	acc, err := acm.GetMutableAccount(state, permission.GlobalPermissionsAddress)
+	acc, err := state.GetMutableAccount(stateWriter, acm.GlobalPermissionsAddress)
 	if err != nil {
 		return nil, err
 	}
@@ -440,15 +449,15 @@ func setGlobal(state acm.StateWriter, caller acm.Account, args []byte, gas *uint
 	if err = acc.MutablePermissions().Base.Set(permN, permV); err != nil {
 		return nil, err
 	}
-	state.UpdateAccount(acc)
-	logger.Trace("function", "setGlobal",
+	stateWriter.UpdateAccount(acc)
+	logger.Trace.Log("function", "setGlobal",
 		"permission_flag", fmt.Sprintf("%b", permN),
 		"permission_value", permV)
 	return permBytes(acc.Permissions().Base.ResultantPerms()), nil
 }
 
-func hasRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func hasRole(state state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	addrWord256, role := returnTwoArgs(args)
 	address := acm.AddressFromWord256(addrWord256)
@@ -462,18 +471,18 @@ func hasRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64
 	roleS := string(role.Bytes())
 	hasRole := acc.Permissions().HasRole(roleS)
 	permInt := byteFromBool(hasRole)
-	logger.Trace("function", "hasRole", "address", address.String(),
+	logger.Trace.Log("function", "hasRole", "address", address.String(),
 		"role", roleS,
 		"has_role", hasRole)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func addRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func addRole(stateWriter state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	addrWord256, role := returnTwoArgs(args)
 	address := acm.AddressFromWord256(addrWord256)
-	acc, err := acm.GetMutableAccount(state, address)
+	acc, err := state.GetMutableAccount(stateWriter, address)
 	if err != nil {
 		return nil, err
 	}
@@ -483,19 +492,19 @@ func addRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64
 	roleS := string(role.Bytes())
 	roleAdded := acc.MutablePermissions().AddRole(roleS)
 	permInt := byteFromBool(roleAdded)
-	state.UpdateAccount(acc)
-	logger.Trace("function", "addRole", "address", address.String(),
+	stateWriter.UpdateAccount(acc)
+	logger.Trace.Log("function", "addRole", "address", address.String(),
 		"role", roleS,
 		"role_added", roleAdded)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func removeRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
-	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+func removeRole(stateWriter state.Writer, caller acm.Account, args []byte, gas *uint64,
+	logger *logging.Logger) (output []byte, err error) {
 
 	addrWord256, role := returnTwoArgs(args)
 	address := acm.AddressFromWord256(addrWord256)
-	acc, err := acm.GetMutableAccount(state, address)
+	acc, err := state.GetMutableAccount(stateWriter, address)
 	if err != nil {
 		return nil, err
 	}
@@ -505,8 +514,8 @@ func removeRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uin
 	roleS := string(role.Bytes())
 	roleRemoved := acc.MutablePermissions().RmRole(roleS)
 	permInt := byteFromBool(roleRemoved)
-	state.UpdateAccount(acc)
-	logger.Trace("function", "removeRole", "address", address.String(),
+	stateWriter.UpdateAccount(acc)
+	logger.Trace.Log("function", "removeRole", "address", address.String(),
 		"role", roleS,
 		"role_removed", roleRemoved)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
@@ -515,23 +524,14 @@ func removeRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uin
 //------------------------------------------------------------------------------------------------
 // Errors and utility funcs
 
-type ErrLacksSNativePermission struct {
-	Address acm.Address
-	SNative string
-}
-
-func (e ErrLacksSNativePermission) Error() string {
-	return fmt.Sprintf("account %s does not have SNative function call permission: %s", e.Address, e.SNative)
-}
-
 // Checks if a permission flag is valid (a known base chain or snative permission)
 func ValidPermN(n ptypes.PermFlag) bool {
 	return n <= permission.AllPermFlags
 }
 
 // Get the global BasePermissions
-func globalPerms(state acm.StateWriter) ptypes.BasePermissions {
-	return permission.GlobalAccountPermissions(state).Base
+func globalPerms(stateWriter state.Writer) ptypes.BasePermissions {
+	return state.GlobalAccountPermissions(stateWriter).Base
 }
 
 // Compute the effective permissions from an acm.Account's BasePermissions by
diff --git a/execution/evm/stack.go b/execution/evm/stack.go
index 2db8018355dab6635a48dcd246254d79780f01f5..3e9dfd5b8987707f68334e6b56f7044bc8fd409c 100644
--- a/execution/evm/stack.go
+++ b/execution/evm/stack.go
@@ -103,14 +103,20 @@ func (st *Stack) PopBytes() []byte {
 	return st.Pop().Bytes()
 }
 
-func (st *Stack) Pop64() int64 {
+func (st *Stack) Pop64() (int64, error) {
 	d := st.Pop()
-	return Int64FromWord256(d)
+	if Is64BitOverflow(d) {
+		return 0, fmt.Errorf("int64 overflow from word: %v", d)
+	}
+	return Int64FromWord256(d), nil
 }
 
-func (st *Stack) PopU64() uint64 {
+func (st *Stack) PopU64() (uint64, error) {
 	d := st.Pop()
-	return Uint64FromWord256(d)
+	if Is64BitOverflow(d) {
+		return 0, fmt.Errorf("uint64 overflow from word: %v", d)
+	}
+	return Uint64FromWord256(d), nil
 }
 
 func (st *Stack) PopBigIntSigned() *big.Int {
@@ -169,3 +175,12 @@ func (st *Stack) Print(n int) {
 	}
 	fmt.Println("#############")
 }
+
+func Is64BitOverflow(word Word256) bool {
+	for i := 0; i < len(word)-8; i++ {
+		if word[i] != 0 {
+			return true
+		}
+	}
+	return false
+}
diff --git a/execution/evm/vm.go b/execution/evm/vm.go
index 98fd2943281ce862ed1bdcda0e7fc60eb811dd19..f94cf768ea702cde7fd208e7fb117cc96ab68d46 100644
--- a/execution/evm/vm.go
+++ b/execution/evm/vm.go
@@ -18,15 +18,18 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
+	"io/ioutil"
+	"math/big"
+	"strings"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/event"
 	. "github.com/hyperledger/burrow/execution/evm/asm"
 	"github.com/hyperledger/burrow/execution/evm/events"
 	"github.com/hyperledger/burrow/execution/evm/sha3"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/permission"
 	ptypes "github.com/hyperledger/burrow/permission/types"
 )
@@ -45,6 +48,12 @@ var (
 	ErrDataStackUnderflow     = errors.New("Data stack underflow")
 	ErrInvalidContract        = errors.New("Invalid contract")
 	ErrNativeContractCodeCopy = errors.New("Tried to copy native contract code")
+	ErrExecutionReverted      = errors.New("Execution reverted")
+)
+
+const (
+	dataStackCapacity = 1024
+	callStackCapacity = 100 // TODO ensure usage.
 )
 
 type ErrPermission struct {
@@ -55,10 +64,36 @@ func (err ErrPermission) Error() string {
 	return fmt.Sprintf("Contract does not have permission to %s", err.typ)
 }
 
-const (
-	dataStackCapacity = 1024
-	callStackCapacity = 100 // TODO ensure usage.
-)
+type ErrNestedCall struct {
+	NestedError error
+	Caller      acm.Address
+	Callee      acm.Address
+	StackDepth  int
+}
+
+func (err ErrNestedCall) Error() string {
+	return fmt.Sprintf("error in nested call at depth %v: %s (callee) -> %s (caller): %v",
+		err.StackDepth, err.Callee, err.Caller, err.NestedError)
+}
+
+type ErrCall struct {
+	CallError    error
+	NestedErrors []ErrNestedCall
+}
+
+func (err ErrCall) Error() string {
+	buf := new(bytes.Buffer)
+	buf.WriteString("call error: ")
+	buf.WriteString(err.CallError.Error())
+	if len(err.NestedErrors) > 0 {
+		buf.WriteString(", nested call errors:\n")
+		for _, nestedErr := range err.NestedErrors {
+			buf.WriteString(nestedErr.Error())
+			buf.WriteByte('\n')
+		}
+	}
+	return buf.String()
+}
 
 type Params struct {
 	BlockHeight uint64
@@ -68,31 +103,40 @@ type Params struct {
 }
 
 type VM struct {
-	state          acm.StateWriter
-	memoryProvider func() Memory
-	params         Params
-	origin         acm.Address
-	txHash         []byte
-	callDepth      int
-	publisher      event.Publisher
-	logger         logging_types.InfoTraceLogger
+	stateWriter      state.Writer
+	memoryProvider   func() Memory
+	params           Params
+	origin           acm.Address
+	txHash           []byte
+	stackDepth       int
+	nestedCallErrors []ErrNestedCall
+	publisher        event.Publisher
+	logger           *logging.Logger
+	debugOpcodes     bool
+	dumpTokens       bool
 }
 
-func NewVM(state acm.StateWriter, memoryProvider func() Memory, params Params, origin acm.Address, txid []byte,
-	logger logging_types.InfoTraceLogger) *VM {
-	return &VM{
-		state:          state,
-		memoryProvider: memoryProvider,
+func NewVM(stateWriter state.Writer, params Params, origin acm.Address, txid []byte,
+	logger *logging.Logger, options ...func(*VM)) *VM {
+	vm := &VM{
+		stateWriter:    stateWriter,
+		memoryProvider: DefaultDynamicMemoryProvider,
 		params:         params,
 		origin:         origin,
-		callDepth:      0,
+		stackDepth:     0,
 		txHash:         txid,
-		logger:         logging.WithScope(logger, "NewVM"),
+		logger:         logger.WithScope("NewVM"),
 	}
+	for _, option := range options {
+		option(vm)
+	}
+	return vm
 }
 
 func (vm *VM) Debugf(format string, a ...interface{}) {
-	logging.TraceMsg(vm.logger, fmt.Sprintf(format, a...), "tag", "vm_debug")
+	if vm.debugOpcodes {
+		vm.logger.TraceMsg(fmt.Sprintf(format, a...), "tag", "DebugOpcodes")
+	}
 }
 
 // satisfies go_events.Eventable
@@ -106,8 +150,8 @@ func (vm *VM) SetPublisher(publisher event.Publisher) {
 // on known permissions and panics else)
 // If the perm is not defined in the acc nor set by default in GlobalPermissions,
 // this function returns false.
-func HasPermission(state acm.StateWriter, acc acm.Account, perm ptypes.PermFlag) bool {
-	value, _ := acc.Permissions().Base.Compose(permission.GlobalAccountPermissions(state).Base).Get(perm)
+func HasPermission(stateWriter state.Writer, acc acm.Account, perm ptypes.PermFlag) bool {
+	value, _ := acc.Permissions().Base.Compose(state.GlobalAccountPermissions(stateWriter).Base).Get(perm)
 	return value
 }
 
@@ -142,17 +186,25 @@ func (vm *VM) Call(caller, callee acm.MutableAccount, code, input []byte, value
 	}
 
 	if len(code) > 0 {
-		vm.callDepth += 1
+		vm.stackDepth += 1
 		output, err = vm.call(caller, callee, code, input, value, gas)
-		vm.callDepth -= 1
+		vm.stackDepth -= 1
 		if err != nil {
+			err = ErrCall{
+				CallError:    err,
+				NestedErrors: vm.nestedCallErrors,
+			}
 			*exception = err.Error()
-			err := transfer(callee, caller, value)
-			if err != nil {
-				// data has been corrupted in ram
-				panic("Could not return value to caller")
+			transferErr := transfer(callee, caller, value)
+			if transferErr != nil {
+				return nil, fmt.Errorf("error transferring value %v %s (callee) -> %s (caller)",
+					value, callee, caller)
 			}
 		}
+		if vm.stackDepth == 0 {
+			// clean up ready for next call
+			vm.nestedCallErrors = nil
+		}
 	}
 
 	return
@@ -162,7 +214,7 @@ func (vm *VM) Call(caller, callee acm.MutableAccount, code, input []byte, value
 // The intent of delegate call is to run the code of the callee in the storage context of the caller;
 // while preserving the original caller to the previous callee.
 // Different to the normal CALL or CALLCODE, the value does not need to be transferred to the callee.
-func (vm *VM) DelegateCall(caller, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
+func (vm *VM) DelegateCall(caller acm.Account, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
 
 	exception := new(string)
 	// fire the post call event (including exception if applicable)
@@ -173,9 +225,9 @@ func (vm *VM) DelegateCall(caller, callee acm.MutableAccount, code, input []byte
 	// DelegateCall does not transfer the value to the callee.
 
 	if len(code) > 0 {
-		vm.callDepth += 1
+		vm.stackDepth += 1
 		output, err = vm.call(caller, callee, code, input, value, gas)
-		vm.callDepth -= 1
+		vm.stackDepth -= 1
 		if err != nil {
 			*exception = err.Error()
 		}
@@ -197,10 +249,16 @@ func useGasNegative(gasLeft *uint64, gasToUse uint64, err *error) bool {
 }
 
 // Just like Call() but does not transfer 'value' or modify the callDepth.
-func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
-	vm.Debugf("(%d) (%X) %X (code=%d) gas: %v (d) %X\n", vm.callDepth, caller.Address().Bytes()[:4], callee.Address(),
+func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
+	vm.Debugf("(%d) (%X) %X (code=%d) gas: %v (d) %X\n", vm.stackDepth, caller.Address().Bytes()[:4], callee.Address(),
 		len(callee.Code()), *gas, input)
 
+	logger := vm.logger.With("tx_hash", vm.txHash)
+
+	if vm.dumpTokens {
+		dumpTokens(vm.txHash, caller, callee, code)
+	}
+
 	var (
 		pc     int64 = 0
 		stack        = NewStack(dataStackCapacity, gas, &err)
@@ -220,19 +278,19 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 
 		case ADD: // 0x01
 			x, y := stack.PopBigInt(), stack.PopBigInt()
-			sum := x.Add(x, y)
+			sum := new(big.Int).Add(x, y)
 			res := stack.PushBigInt(sum)
 			vm.Debugf(" %v + %v = %v (%X)\n", x, y, sum, res)
 
 		case MUL: // 0x02
 			x, y := stack.PopBigInt(), stack.PopBigInt()
-			prod := x.Mul(x, y)
+			prod := new(big.Int).Mul(x, y)
 			res := stack.PushBigInt(prod)
 			vm.Debugf(" %v * %v = %v (%X)\n", x, y, prod, res)
 
 		case SUB: // 0x03
 			x, y := stack.PopBigInt(), stack.PopBigInt()
-			diff := x.Sub(x, y)
+			diff := new(big.Int).Sub(x, y)
 			res := stack.PushBigInt(diff)
 			vm.Debugf(" %v - %v = %v (%X)\n", x, y, diff, res)
 
@@ -242,7 +300,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(Zero256)
 				vm.Debugf(" %x / %x = %v\n", x, y, 0)
 			} else {
-				div := x.Div(x, y)
+				div := new(big.Int).Div(x, y)
 				res := stack.PushBigInt(div)
 				vm.Debugf(" %v / %v = %v (%X)\n", x, y, div, res)
 			}
@@ -253,7 +311,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(Zero256)
 				vm.Debugf(" %x / %x = %v\n", x, y, 0)
 			} else {
-				div := x.Div(x, y)
+				div := new(big.Int).Div(x, y)
 				res := stack.PushBigInt(div)
 				vm.Debugf(" %v / %v = %v (%X)\n", x, y, div, res)
 			}
@@ -264,7 +322,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				mod := x.Mod(x, y)
+				mod := new(big.Int).Mod(x, y)
 				res := stack.PushBigInt(mod)
 				vm.Debugf(" %v %% %v = %v (%X)\n", x, y, mod, res)
 			}
@@ -275,7 +333,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				mod := x.Mod(x, y)
+				mod := new(big.Int).Mod(x, y)
 				res := stack.PushBigInt(mod)
 				vm.Debugf(" %v %% %v = %v (%X)\n", x, y, mod, res)
 			}
@@ -286,7 +344,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				add := x.Add(x, y)
+				add := new(big.Int).Add(x, y)
 				mod := add.Mod(add, z)
 				res := stack.PushBigInt(mod)
 				vm.Debugf(" %v + %v %% %v = %v (%X)\n", x, y, z, mod, res)
@@ -298,7 +356,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				mul := x.Mul(x, y)
+				mul := new(big.Int).Mul(x, y)
 				mod := mul.Mod(mul, z)
 				res := stack.PushBigInt(mod)
 				vm.Debugf(" %v * %v %% %v = %v (%X)\n", x, y, z, mod, res)
@@ -306,12 +364,15 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 
 		case EXP: // 0x0A
 			x, y := stack.PopBigInt(), stack.PopBigInt()
-			pow := x.Exp(x, y, nil)
+			pow := new(big.Int).Exp(x, y, nil)
 			res := stack.PushBigInt(pow)
 			vm.Debugf(" %v ** %v = %v (%X)\n", x, y, pow, res)
 
 		case SIGNEXTEND: // 0x0B
-			back := stack.PopU64()
+			back, popErr := stack.PopU64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			if back < Word256Length-1 {
 				stack.PushBigInt(SignExtend(back, stack.PopBigInt()))
 			}
@@ -413,7 +474,11 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" !%X = %X\n", x, z)
 
 		case BYTE: // 0x1A
-			idx, val := stack.Pop64(), stack.Pop()
+			idx, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			val := stack.Pop()
 			res := byte(0)
 			if idx < 32 {
 				res = val[idx]
@@ -444,7 +509,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc, errAcc := vm.state.GetAccount(acm.AddressFromWord256(addr))
+			acc, errAcc := vm.stateWriter.GetAccount(acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -468,7 +533,10 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => %v\n", value)
 
 		case CALLDATALOAD: // 0x35
-			offset := stack.Pop64()
+			offset, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			data, ok := subslice(input, offset, 32)
 			if !ok {
 				return nil, firstErr(err, ErrInputOutOfBounds)
@@ -483,8 +551,14 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 
 		case CALLDATACOPY: // 0x37
 			memOff := stack.PopBigInt()
-			inputOff := stack.Pop64()
-			length := stack.Pop64()
+			inputOff, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			length, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			data, ok := subslice(input, inputOff, length)
 			if !ok {
 				return nil, firstErr(err, ErrInputOutOfBounds)
@@ -503,8 +577,14 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 
 		case CODECOPY: // 0x39
 			memOff := stack.PopBigInt()
-			codeOff := stack.Pop64()
-			length := stack.Pop64()
+			codeOff, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			length, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			data, ok := subslice(code, codeOff, length)
 			if !ok {
 				return nil, firstErr(err, ErrCodeOutOfBounds)
@@ -525,7 +605,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc, errAcc := vm.state.GetAccount(acm.AddressFromWord256(addr))
+			acc, errAcc := vm.stateWriter.GetAccount(acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -546,7 +626,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc, errAcc := vm.state.GetAccount(acm.AddressFromWord256(addr))
+			acc, errAcc := vm.stateWriter.GetAccount(acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -559,8 +639,14 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			}
 			code := acc.Code()
 			memOff := stack.PopBigInt()
-			codeOff := stack.Pop64()
-			length := stack.Pop64()
+			codeOff, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			length, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			data, ok := subslice(code, codeOff, length)
 			if !ok {
 				return nil, firstErr(err, ErrCodeOutOfBounds)
@@ -618,7 +704,12 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => 0x%X @ 0x%X\n", data, offset)
 
 		case MSTORE8: // 0x53
-			offset, val := stack.PopBigInt(), byte(stack.Pop64()&0xFF)
+			offset := stack.PopBigInt()
+			val64, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			val := byte(val64 & 0xFF)
 			memErr := memory.Write(offset, []byte{val})
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
@@ -628,23 +719,27 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 
 		case SLOAD: // 0x54
 			loc := stack.Pop()
-			data, errSto := vm.state.GetStorage(callee.Address(), loc)
+			data, errSto := vm.stateWriter.GetStorage(callee.Address(), loc)
 			if errSto != nil {
 				return nil, firstErr(err, errSto)
 			}
 			stack.Push(data)
-			vm.Debugf(" {0x%X : 0x%X}\n", loc, data)
+			vm.Debugf("%s {0x%X = 0x%X}\n", callee.Address(), loc, data)
 
 		case SSTORE: // 0x55
 			loc, data := stack.Pop(), stack.Pop()
 			if useGasNegative(gas, GasStorageUpdate, &err) {
 				return nil, err
 			}
-			vm.state.SetStorage(callee.Address(), loc, data)
-			vm.Debugf(" {0x%X : 0x%X}\n", loc, data)
+			vm.stateWriter.SetStorage(callee.Address(), loc, data)
+			vm.Debugf("%s {0x%X := 0x%X}\n", callee.Address(), loc, data)
 
 		case JUMP: // 0x56
-			jumpErr := vm.jump(code, stack.Pop64(), &pc)
+			to, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			jumpErr := vm.jump(code, to, &pc)
 			if jumpErr != nil {
 				vm.Debugf(" => JUMP err: %s", jumpErr)
 				return nil, firstErr(err, jumpErr)
@@ -652,7 +747,11 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			continue
 
 		case JUMPI: // 0x57
-			pos, cond := stack.Pop64(), stack.Pop()
+			pos, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
+			cond := stack.Pop()
 			if !cond.IsZero() {
 				jumpErr := vm.jump(code, pos, &pc)
 				if jumpErr != nil {
@@ -717,8 +816,6 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 			if vm.publisher != nil {
-				eventID := events.EventStringLogEvent(callee.Address())
-				fmt.Printf("eventID: %s\n", eventID)
 				events.PublishLogEvent(vm.publisher, callee.Address(), &events.EventDataLog{
 					Address: callee.Address(),
 					Topics:  topics,
@@ -729,10 +826,13 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => T:%X D:%X\n", topics, data)
 
 		case CREATE: // 0xF0
-			if !HasPermission(vm.state, callee, permission.CreateContract) {
+			if !HasPermission(vm.stateWriter, callee, permission.CreateContract) {
 				return nil, ErrPermission{"create_contract"}
 			}
-			contractValue := stack.PopU64()
+			contractValue, popErr := stack.PopU64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			offset, size := stack.PopBigInt(), stack.PopBigInt()
 			input, memErr := memory.Read(offset, size)
 			if memErr != nil {
@@ -746,9 +846,14 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			}
 
 			// TODO charge for gas to create account _ the code length * GasCreateByte
-			newAccount := DeriveNewAccount(callee, permission.GlobalAccountPermissions(vm.state),
-				vm.logger.With("tx_hash", vm.txHash))
-			vm.state.UpdateAccount(newAccount)
+			var gasErr error
+			if useGasNegative(gas, GasCreateAccount, &gasErr) {
+				return nil, firstErr(err, gasErr)
+			}
+			newAccount, createErr := vm.createAccount(callee, logger)
+			if createErr != nil {
+				return nil, firstErr(err, createErr)
+			}
 
 			// Run the input to get the contract code.
 			// NOTE: no need to copy 'input' as per Call contract.
@@ -760,11 +865,18 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				stack.Push(newAccount.Address().Word256())
 			}
 
+			if err_ == ErrExecutionReverted {
+				return ret, nil
+			}
+
 		case CALL, CALLCODE, DELEGATECALL: // 0xF1, 0xF2, 0xF4
-			if !HasPermission(vm.state, callee, permission.Call) {
+			if !HasPermission(vm.stateWriter, callee, permission.Call) {
 				return nil, ErrPermission{"call"}
 			}
-			gasLimit := stack.PopU64()
+			gasLimit, popErr := stack.PopU64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
+			}
 			addr := stack.Pop()
 			// NOTE: for DELEGATECALL value is preserved from the original
 			// caller, as such it is not stored on stack as an argument
@@ -772,10 +884,19 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			// caller value is used.  for CALL and CALLCODE value is stored
 			// on stack and needs to be overwritten from the given value.
 			if op != DELEGATECALL {
-				value = stack.PopU64()
+				value, popErr = stack.PopU64()
+				if popErr != nil {
+					return nil, firstErr(err, popErr)
+				}
+			}
+			// inputs
+			inOffset, inSize := stack.PopBigInt(), stack.PopBigInt()
+			// outputs
+			retOffset := stack.PopBigInt()
+			retSize, popErr := stack.Pop64()
+			if popErr != nil {
+				return nil, firstErr(err, popErr)
 			}
-			inOffset, inSize := stack.PopBigInt(), stack.PopBigInt() // inputs
-			retOffset, retSize := stack.PopBigInt(), stack.Pop64()   // outputs
 			vm.Debugf(" => %X\n", addr)
 
 			// Get the arguments from the memory
@@ -787,18 +908,19 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 
 			// Ensure that gasLimit is reasonable
 			if *gas < gasLimit {
-				return nil, firstErr(err, ErrInsufficientGas)
-			} else {
-				*gas -= gasLimit
-				// NOTE: we will return any used gas later.
+				// EIP150 - the 63/64 rule - rather than error we pass this specified fraction of the total available gas
+				gasLimit = *gas - *gas/64
 			}
+			// NOTE: we will return any used gas later.
+			*gas -= gasLimit
 
 			// Begin execution
 			var ret []byte
 			var callErr error
+
 			if nativeContract := registeredNativeContracts[addr]; nativeContract != nil {
 				// Native contract
-				ret, callErr = nativeContract(vm.state, callee, args, &gasLimit, vm.logger)
+				ret, callErr = nativeContract(vm.stateWriter, callee, args, &gasLimit, logger)
 
 				// for now we fire the Call event. maybe later we'll fire more particulars
 				var exception string
@@ -812,7 +934,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				if useGasNegative(gas, GasGetAccount, &callErr) {
 					return nil, callErr
 				}
-				acc, errAcc := acm.GetMutableAccount(vm.state, acm.AddressFromWord256(addr))
+				acc, errAcc := state.GetMutableAccount(vm.stateWriter, acm.AddressFromWord256(addr))
 				if errAcc != nil {
 					return nil, firstErr(callErr, errAcc)
 				}
@@ -833,23 +955,43 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				} else {
 					// nil account means we're sending funds to a new account
 					if acc == nil {
-						if !HasPermission(vm.state, caller, permission.CreateAccount) {
+						if !HasPermission(vm.stateWriter, caller, permission.CreateAccount) {
 							return nil, ErrPermission{"create_account"}
 						}
-						acc = (&acm.ConcreteAccount{Address: acm.AddressFromWord256(addr)}).MutableAccount()
+						acc = acm.ConcreteAccount{Address: acm.AddressFromWord256(addr)}.MutableAccount()
 					}
 					// add account to the tx cache
-					vm.state.UpdateAccount(acc)
+					vm.stateWriter.UpdateAccount(acc)
 					ret, callErr = vm.Call(callee, acc, acc.Code(), args, value, &gasLimit)
 				}
 			}
+			// In case any calls deeper in the stack (particularly SNatives) has altered either of two accounts to which
+			// we hold a reference, we need to freshen our state for subsequent iterations of this call frame's EVM loop
+			var getErr error
+			caller, getErr = vm.stateWriter.GetAccount(caller.Address())
+			if getErr != nil {
+				return nil, firstErr(err, getErr)
+			}
+			callee, getErr = state.GetMutableAccount(vm.stateWriter, callee.Address())
+			if getErr != nil {
+				return nil, firstErr(err, getErr)
+			}
 
 			// Push result
 			if callErr != nil {
-				vm.Debugf("error on call: %s\n", callErr.Error())
-				// TODO: we probably don't want to return the error - decide
-				//err = firstErr(err, callErr)
+				vm.Debugf("error from nested sub-call (depth: %v): %s\n", vm.stackDepth, callErr.Error())
+				// So we can return nested error if the top level return is an error
+				vm.nestedCallErrors = append(vm.nestedCallErrors, ErrNestedCall{
+					NestedError: callErr,
+					StackDepth:  vm.stackDepth,
+					Caller:      caller.Address(),
+					Callee:      callee.Address(),
+				})
 				stack.Push(Zero256)
+
+				if callErr == ErrExecutionReverted {
+					memory.Write(retOffset, RightPadBytes(ret, int(retSize)))
+				}
 			} else {
 				stack.Push(One256)
 
@@ -878,42 +1020,78 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
 			return output, nil
 
+		case REVERT: // 0xFD
+			return nil, fmt.Errorf("REVERT not yet fully implemented")
+			offset, size := stack.PopBigInt(), stack.PopBigInt()
+			output, memErr := memory.Read(offset, size)
+			if memErr != nil {
+				vm.Debugf(" => Memory err: %s", memErr)
+				return nil, firstErr(err, ErrMemoryOutOfBounds)
+			}
+
+			vm.Debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
+			return output, ErrExecutionReverted
+
 		case SELFDESTRUCT: // 0xFF
 			addr := stack.Pop()
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			// TODO if the receiver is , then make it the fee. (?)
-			// TODO: create account if doesn't exist (no reason not to)
-			receiver, errAcc := acm.GetMutableAccount(vm.state, acm.AddressFromWord256(addr))
+			receiver, errAcc := state.GetMutableAccount(vm.stateWriter, acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
 			if receiver == nil {
-				return nil, firstErr(err, ErrUnknownAddress)
+				var gasErr error
+				if useGasNegative(gas, GasCreateAccount, &gasErr) {
+					return nil, firstErr(err, gasErr)
+				}
+				if !HasPermission(vm.stateWriter, callee, permission.CreateContract) {
+					return nil, firstErr(err, ErrPermission{"create_contract"})
+				}
+				var createErr error
+				receiver, createErr = vm.createAccount(callee, logger)
+				if createErr != nil {
+					return nil, firstErr(err, createErr)
+				}
+
 			}
 
 			receiver, errAdd := receiver.AddToBalance(callee.Balance())
 			if errAdd != nil {
 				return nil, firstErr(err, errAdd)
 			}
-			vm.state.UpdateAccount(receiver)
-			vm.state.RemoveAccount(callee.Address())
+			vm.stateWriter.UpdateAccount(receiver)
+			vm.stateWriter.RemoveAccount(callee.Address())
 			vm.Debugf(" => (%X) %v\n", addr[:4], callee.Balance())
 			fallthrough
 
 		case STOP: // 0x00
 			return nil, nil
 
+		case STATICCALL, SHL, SHR, SAR, RETURNDATASIZE, RETURNDATACOPY:
+			return nil, fmt.Errorf("%s not yet implemented", op.Name())
 		default:
 			vm.Debugf("(pc) %-3v Invalid opcode %X\n", pc, op)
-			return nil, fmt.Errorf("Invalid opcode %X", op)
+			return nil, fmt.Errorf("invalid opcode %X", op)
 		}
-
 		pc++
 	}
 }
 
+func (vm *VM) createAccount(callee acm.MutableAccount, logger *logging.Logger) (acm.MutableAccount, error) {
+	newAccount := DeriveNewAccount(callee, state.GlobalAccountPermissions(vm.stateWriter), logger)
+	err := vm.stateWriter.UpdateAccount(newAccount)
+	if err != nil {
+		return nil, err
+	}
+	err = vm.stateWriter.UpdateAccount(callee)
+	if err != nil {
+		return nil, err
+	}
+	return newAccount, nil
+}
+
 // TODO: [Silas] this function seems extremely dubious to me. It was being used
 // in circumstances where its behaviour did not match the intention. It's bounds
 // check is strange (treats a read at data length as a zero read of arbitrary length)
@@ -976,3 +1154,28 @@ func transfer(from, to acm.MutableAccount, amount uint64) error {
 	}
 	return nil
 }
+
+// Dump the bytecode being sent to the EVM in the current working directory
+func dumpTokens(txHash []byte, caller, callee acm.Account, code []byte) {
+	var tokensString string
+	tokens, err := acm.Bytecode(code).Tokens()
+	if err != nil {
+		tokensString = fmt.Sprintf("error generating tokens from bytecode: %v", err)
+	} else {
+		tokensString = strings.Join(tokens, "\n")
+	}
+	txHashString := "tx-none"
+	if len(txHash) >= 4 {
+		txHashString = fmt.Sprintf("tx-%X", txHash[:4])
+	}
+	callerString := "caller-none"
+	if caller != nil {
+		callerString = fmt.Sprintf("caller-%v", caller.Address())
+	}
+	calleeString := "callee-none"
+	if callee != nil {
+		calleeString = fmt.Sprintf("callee-%s", caller.Address())
+	}
+	ioutil.WriteFile(fmt.Sprintf("tokens_%s_%s_%s.asm", txHashString, callerString, calleeString),
+		[]byte(tokensString), 0777)
+}
diff --git a/execution/evm/vm_test.go b/execution/evm/vm_test.go
index a6335deeb28622fdd99c1c985871cd3e8cb35359..82d79012b6127a72fe7f4ae112613041145c8bcf 100644
--- a/execution/evm/vm_test.go
+++ b/execution/evm/vm_test.go
@@ -24,12 +24,13 @@ import (
 	"time"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/event"
 	. "github.com/hyperledger/burrow/execution/evm/asm"
 	. "github.com/hyperledger/burrow/execution/evm/asm/bc"
 	evm_events "github.com/hyperledger/burrow/execution/evm/events"
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/permission"
 	ptypes "github.com/hyperledger/burrow/permission/types"
 	"github.com/stretchr/testify/assert"
@@ -38,8 +39,9 @@ import (
 )
 
 // Test output is a bit clearer if we /dev/null the logging, but can be re-enabled by uncommenting the below
-//var logger, _ = lifecycle.NewStdErrLogger()
-var logger = loggers.NewNoopInfoTraceLogger()
+//var logger, _, _ = lifecycle.NewStdErrLogger()
+//
+var logger = logging.NewNoopLogger()
 
 func newAppState() *FakeAppState {
 	fas := &FakeAppState{
@@ -47,7 +49,7 @@ func newAppState() *FakeAppState {
 		storage:  make(map[string]Word256),
 	}
 	// For default permissions
-	fas.accounts[permission.GlobalPermissionsAddress] = acm.ConcreteAccount{
+	fas.accounts[acm.GlobalPermissionsAddress] = acm.ConcreteAccount{
 		Permissions: permission.DefaultAccountPermissions,
 	}.Account()
 	return fas
@@ -72,7 +74,7 @@ func newAccount(seed ...byte) acm.MutableAccount {
 
 // Runs a basic loop
 func TestVM(t *testing.T) {
-	ourVm := NewVM(newAppState(), DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
@@ -95,7 +97,7 @@ func TestVM(t *testing.T) {
 
 //Test attempt to jump to bad destination (position 16)
 func TestJumpErr(t *testing.T) {
-	ourVm := NewVM(newAppState(), DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
@@ -132,7 +134,7 @@ func TestSubcurrency(t *testing.T) {
 	st.accounts[account1.Address()] = account1
 	st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(st, newParams(), acm.ZeroAddress, nil, logger)
 
 	var gas uint64 = 1000
 
@@ -158,16 +160,41 @@ func TestSubcurrency(t *testing.T) {
 	}
 }
 
+//This test case is taken from EIP-140 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md);
+//it is meant to test the implementation of the REVERT opcode
+func TestRevert(t *testing.T) {
+	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+
+	// Create accounts
+	account1 := newAccount(1)
+	account2 := newAccount(1, 0, 1)
+
+	var gas uint64 = 100000
+
+	bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61,
+		0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT)
+
+	start := time.Now()
+	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	assert.Error(t, err, "Expected execution reverted error")
+	fmt.Printf("Output: %v Error: %v\n", output, err)
+	fmt.Println("Call took:", time.Since(start))
+}
+
 // Test sending tokens from a contract to another account
 func TestSendCall(t *testing.T) {
 	fakeAppState := newAppState()
-	ourVm := NewVM(fakeAppState, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(fakeAppState, newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
 	account2 := newAccount(2)
 	account3 := newAccount(3)
 
+	fakeAppState.UpdateAccount(account1)
+	fakeAppState.UpdateAccount(account2)
+	fakeAppState.UpdateAccount(account3)
 	// account1 will call account2 which will trigger CALL opcode to account3
 	addr := account3.Address()
 	contractCode := callContractCode(addr)
@@ -189,7 +216,7 @@ func TestSendCall(t *testing.T) {
 	account2, err = newAccount(2).AddToBalance(100000)
 	require.NoError(t, err)
 	_, err = runVMWaitError(ourVm, account1, account2, addr, contractCode, 100)
-	assert.Error(t, err, "Expected insufficient gas error")
+	assert.NoError(t, err, "Expected insufficient gas error")
 }
 
 // This test was introduced to cover an issues exposed in our handling of the
@@ -198,8 +225,8 @@ func TestSendCall(t *testing.T) {
 // We first run the DELEGATECALL with _just_ enough gas expecting a simple return,
 // and then run it with 1 gas unit less, expecting a failure
 func TestDelegateCallGas(t *testing.T) {
-	state := newAppState()
-	ourVm := NewVM(state, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	appState := newAppState()
+	ourVm := NewVM(appState, newParams(), acm.ZeroAddress, nil, logger)
 
 	inOff := 0
 	inSize := 0 // no call data
@@ -219,7 +246,7 @@ func TestDelegateCallGas(t *testing.T) {
 	costBetweenGasAndDelegateCall := gasCost + subCost + delegateCallCost + pushCost
 
 	// Do a simple operation using 1 gas unit
-	calleeAccount, calleeAddress := makeAccountWithCode(state, "callee",
+	calleeAccount, calleeAddress := makeAccountWithCode(appState, "callee",
 		MustSplice(PUSH1, calleeReturnValue, return1()))
 
 	// Here we split up the caller code so we can make a DELEGATE call with
@@ -232,7 +259,7 @@ func TestDelegateCallGas(t *testing.T) {
 	callerCodeSuffix := MustSplice(GAS, SUB, DELEGATECALL, returnWord())
 
 	// Perform a delegate call
-	callerAccount, _ := makeAccountWithCode(state, "caller",
+	callerAccount, _ := makeAccountWithCode(appState, "caller",
 		MustSplice(callerCodePrefix,
 			// Give just enough gas to make the DELEGATECALL
 			costBetweenGasAndDelegateCall,
@@ -252,17 +279,17 @@ func TestDelegateCallGas(t *testing.T) {
 	// Should fail
 	_, err = runVMWaitError(ourVm, callerAccount, calleeAccount, calleeAddress,
 		callerAccount.Code(), 100)
-	assert.Error(t, err, "Should have insufficient funds for call")
+	assert.Error(t, err, "Should have insufficient gas for call")
 }
 
 func TestMemoryBounds(t *testing.T) {
-	state := newAppState()
+	appState := newAppState()
 	memoryProvider := func() Memory {
 		return NewDynamicMemory(1024, 2048)
 	}
-	ourVm := NewVM(state, memoryProvider, newParams(), acm.ZeroAddress, nil, logger)
-	caller, _ := makeAccountWithCode(state, "caller", nil)
-	callee, _ := makeAccountWithCode(state, "callee", nil)
+	ourVm := NewVM(appState, newParams(), acm.ZeroAddress, nil, logger, MemoryProvider(memoryProvider))
+	caller, _ := makeAccountWithCode(appState, "caller", nil)
+	callee, _ := makeAccountWithCode(appState, "callee", nil)
 	gas := uint64(100000)
 	// This attempts to store a value at the memory boundary and return it
 	word := One256
@@ -307,7 +334,7 @@ func TestMsgSender(t *testing.T) {
 	st.accounts[account1.Address()] = account1
 	st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(st, newParams(), acm.ZeroAddress, nil, logger)
 
 	var gas uint64 = 100000
 
@@ -373,7 +400,7 @@ func returnWord() []byte {
 	return MustSplice(PUSH1, 32, PUSH1, 0, RETURN)
 }
 
-func makeAccountWithCode(state acm.Updater, name string,
+func makeAccountWithCode(accountUpdater state.AccountUpdater, name string,
 	code []byte) (acm.MutableAccount, acm.Address) {
 	address, _ := acm.AddressFromBytes([]byte(name))
 	account := acm.ConcreteAccount{
@@ -382,7 +409,7 @@ func makeAccountWithCode(state acm.Updater, name string,
 		Code:     code,
 		Sequence: 0,
 	}.MutableAccount()
-	state.UpdateAccount(account)
+	accountUpdater.UpdateAccount(account)
 	return account, account.Address()
 }
 
@@ -412,7 +439,7 @@ func runVM(eventCh chan<- *evm_events.EventDataCall, ourVm *VM, caller, callee a
 	subscribeAddr acm.Address, contractCode []byte, gas uint64) ([]byte, error) {
 
 	// we need to catch the event from the CALL to check for exceptions
-	emitter := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
+	emitter := event.NewEmitter(logging.NewNoopLogger())
 	fmt.Printf("subscribe to %s\n", subscribeAddr)
 
 	err := evm_events.SubscribeAccountCall(context.Background(), emitter, "test", subscribeAddr, nil, eventCh)
diff --git a/execution/execution.go b/execution/execution.go
index fbe69f4f4fdddacd6e9d2bc68bcfe03d08b91098..7b5a9ee7ea77cb3c5a6d4d66d68eb118ead05159 100644
--- a/execution/execution.go
+++ b/execution/execution.go
@@ -16,9 +16,11 @@ package execution
 
 import (
 	"fmt"
+	"runtime/debug"
 	"sync"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	"github.com/hyperledger/burrow/binary"
 	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/event"
@@ -26,7 +28,6 @@ import (
 	"github.com/hyperledger/burrow/execution/evm"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/permission"
 	ptypes "github.com/hyperledger/burrow/permission/types"
 	"github.com/hyperledger/burrow/txs"
@@ -36,9 +37,9 @@ import (
 const GasLimit = uint64(1000000)
 
 type BatchExecutor interface {
-	acm.StateIterable
-	acm.Updater
-	acm.StorageSetter
+	state.Iterable
+	state.AccountUpdater
+	state.StorageSetter
 	// Execute transaction against block cache (i.e. block buffer)
 	Execute(tx txs.Tx) error
 	// Reset executor to underlying State
@@ -59,11 +60,12 @@ type executor struct {
 	tip          bcm.Tip
 	runCall      bool
 	state        *State
-	stateCache   acm.StateCache
+	stateCache   state.Cache
 	nameRegCache *NameRegCache
 	publisher    event.Publisher
 	eventCache   *event.Cache
-	logger       logging_types.InfoTraceLogger
+	logger       *logging.Logger
+	vmOptions    []func(*evm.VM)
 }
 
 var _ BatchExecutor = (*executor)(nil)
@@ -72,37 +74,45 @@ var _ BatchExecutor = (*executor)(nil)
 func NewBatchChecker(state *State,
 	chainID string,
 	tip bcm.Tip,
-	logger logging_types.InfoTraceLogger) BatchExecutor {
+	logger *logging.Logger,
+	options ...ExecutionOption) BatchExecutor {
 	return newExecutor(false, state, chainID, tip, event.NewNoOpPublisher(),
-		logging.WithScope(logger, "NewBatchExecutor"))
+		logger.WithScope("NewBatchExecutor"), options...)
 }
 
 func NewBatchCommitter(state *State,
 	chainID string,
 	tip bcm.Tip,
 	publisher event.Publisher,
-	logger logging_types.InfoTraceLogger) BatchCommitter {
+	logger *logging.Logger,
+	options ...ExecutionOption) BatchCommitter {
+
 	return newExecutor(true, state, chainID, tip, publisher,
-		logging.WithScope(logger, "NewBatchCommitter"))
+		logger.WithScope("NewBatchCommitter"), options...)
 }
 
 func newExecutor(runCall bool,
-	state *State,
+	backend *State,
 	chainID string,
 	tip bcm.Tip,
 	eventFireable event.Publisher,
-	logger logging_types.InfoTraceLogger) *executor {
-	return &executor{
+	logger *logging.Logger,
+	options ...ExecutionOption) *executor {
+	exe := &executor{
 		chainID:      chainID,
 		tip:          tip,
 		runCall:      runCall,
-		state:        state,
-		stateCache:   acm.NewStateCache(state),
-		nameRegCache: NewNameRegCache(state),
+		state:        backend,
+		stateCache:   state.NewCache(backend),
+		nameRegCache: NewNameRegCache(backend),
 		publisher:    eventFireable,
 		eventCache:   event.NewEventCache(eventFireable),
 		logger:       logger.With(structure.ComponentKey, "Executor"),
 	}
+	for _, option := range options {
+		option(exe)
+	}
+	return exe
 }
 
 // Accounts
@@ -157,7 +167,7 @@ func (exe *executor) Commit() (hash []byte, err error) {
 	if err != nil {
 		return nil, err
 	}
-	// flush events to listeners (XXX: note issue with blocking)
+	// flush events to listeners
 	exe.eventCache.Flush()
 	return exe.state.Hash(), nil
 }
@@ -173,16 +183,16 @@ func (exe *executor) Reset() error {
 func (exe *executor) Execute(tx txs.Tx) (err error) {
 	defer func() {
 		if r := recover(); r != nil {
-			err = fmt.Errorf("recovered from panic in executor.Execute(%s): %v", tx.String(), r)
+			err = fmt.Errorf("recovered from panic in executor.Execute(%s): %v\n%s", tx.String(), r,
+				debug.Stack())
 		}
 	}()
 
 	txHash := tx.Hash(exe.chainID)
-	logger := logging.WithScope(exe.logger, "executor.Execute(tx txs.Tx)").With(
+	logger := exe.logger.WithScope("executor.Execute(tx txs.Tx)").With(
 		"run_call", exe.runCall,
-		"tx", tx.String(),
 		"tx_hash", txHash)
-	logging.TraceMsg(logger, "Executing transaction", "tx", tx.String())
+	logger.TraceMsg("Executing transaction", "tx", tx.String())
 	// TODO: do something with fees
 	fees := uint64(0)
 
@@ -253,12 +263,12 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 		var outAcc acm.Account
 
 		// Validate input
-		inAcc, err := acm.GetMutableAccount(exe.stateCache, tx.Input.Address)
+		inAcc, err := state.GetMutableAccount(exe.stateCache, tx.Input.Address)
 		if err != nil {
 			return err
 		}
 		if inAcc == nil {
-			logging.InfoMsg(logger, "Cannot find input account",
+			logger.InfoMsg("Cannot find input account",
 				"tx_input", tx.Input)
 			return txs.ErrTxInvalidAddress
 		}
@@ -276,19 +286,19 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 
 		// pubKey should be present in either "inAcc" or "tx.Input"
 		if err := checkInputPubKey(inAcc, tx.Input); err != nil {
-			logging.InfoMsg(logger, "Cannot find public key for input account",
+			logger.InfoMsg("Cannot find public key for input account",
 				"tx_input", tx.Input)
 			return err
 		}
 		signBytes := acm.SignBytes(exe.chainID, tx)
 		err = validateInput(inAcc, signBytes, tx.Input)
 		if err != nil {
-			logging.InfoMsg(logger, "validateInput failed",
+			logger.InfoMsg("validateInput failed",
 				"tx_input", tx.Input, structure.ErrorKey, err)
 			return err
 		}
 		if tx.Input.Amount < tx.Fee {
-			logging.InfoMsg(logger, "Sender did not send enough to cover the fee",
+			logger.InfoMsg("Sender did not send enough to cover the fee",
 				"tx_input", tx.Input)
 			return txs.ErrTxInsufficientFunds
 		}
@@ -312,12 +322,12 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 			}
 		}
 
-		logger.Trace("output_account", outAcc)
+		logger.Trace.Log("output_account", outAcc)
 
 		// Good!
 		value := tx.Input.Amount - tx.Fee
 
-		logging.TraceMsg(logger, "Incrementing sequence number for CallTx",
+		logger.TraceMsg("Incrementing sequence number for CallTx",
 			"tag", "sequence",
 			"account", inAcc.Address(),
 			"old_sequence", inAcc.Sequence(),
@@ -340,7 +350,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 				callee  acm.MutableAccount = nil // initialized below
 				code    []byte             = nil
 				ret     []byte             = nil
-				txCache                    = acm.NewStateCache(exe.stateCache)
+				txCache                    = state.NewCache(exe.stateCache)
 				params                     = evm.Params{
 					BlockHeight: exe.tip.LastBlockHeight(),
 					BlockHash:   binary.LeftPadWord256(exe.tip.LastBlockHash()),
@@ -358,11 +368,11 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 				// you have to wait a block to avoid a re-ordering attack
 				// that will take your fees
 				if outAcc == nil {
-					logging.InfoMsg(logger, "Call to address that does not exist",
+					logger.InfoMsg("Call to address that does not exist",
 						"caller_address", inAcc.Address(),
 						"callee_address", tx.Address)
 				} else {
-					logging.InfoMsg(logger, "Call to address that holds no code",
+					logger.InfoMsg("Call to address that holds no code",
 						"caller_address", inAcc.Address(),
 						"callee_address", tx.Address)
 				}
@@ -373,44 +383,43 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 			// get or create callee
 			if createContract {
 				// We already checked for permission
-				callee = evm.DeriveNewAccount(caller, permission.GlobalAccountPermissions(exe.state),
+				callee = evm.DeriveNewAccount(caller, state.GlobalAccountPermissions(exe.state),
 					logger.With(
 						"tx", tx.String(),
 						"tx_hash", txHash,
 						"run_call", exe.runCall,
 					))
 				code = tx.Data
-				logging.TraceMsg(logger, "Creating new contract",
+				logger.TraceMsg("Creating new contract",
 					"contract_address", callee.Address(),
 					"init_code", code)
 			} else {
 				callee = acm.AsMutableAccount(outAcc)
 				code = callee.Code()
-				logging.TraceMsg(logger, "Calling existing contract",
+				logger.TraceMsg("Calling existing contract",
 					"contract_address", callee.Address(),
 					"input", tx.Data,
 					"contract_code", code)
 			}
-			logger.Trace("callee", callee.Address().String())
+			logger.Trace.Log("callee", callee.Address().String())
 
 			// Run VM call and sync txCache to exe.blockCache.
 			{ // Capture scope for goto.
 				// Write caller/callee to txCache.
 				txCache.UpdateAccount(caller)
 				txCache.UpdateAccount(callee)
-				vmach := evm.NewVM(txCache, evm.DefaultDynamicMemoryProvider, params, caller.Address(),
-					tx.Hash(exe.chainID), logger)
+				vmach := evm.NewVM(txCache, params, caller.Address(), tx.Hash(exe.chainID), logger, exe.vmOptions...)
 				vmach.SetPublisher(exe.eventCache)
 				// NOTE: Call() transfers the value from caller to callee iff call succeeds.
 				ret, err = vmach.Call(caller, callee, code, tx.Data, value, &gas)
 				if err != nil {
 					// Failure. Charge the gas fee. The 'value' was otherwise not transferred.
-					logging.InfoMsg(logger, "Error on execution",
+					logger.InfoMsg("Error on execution",
 						structure.ErrorKey, err)
 					goto CALL_COMPLETE
 				}
 
-				logging.TraceMsg(logger, "Successful execution")
+				logger.TraceMsg("Successful execution")
 				if createContract {
 					callee.SetCode(ret)
 				}
@@ -420,7 +429,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 		CALL_COMPLETE: // err may or may not be nil.
 
 			// Create a receipt from the ret and whether it erred.
-			logging.TraceMsg(logger, "VM call complete",
+			logger.TraceMsg("VM call complete",
 				"caller", caller,
 				"callee", callee,
 				"return", ret,
@@ -450,7 +459,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 			}
 			if createContract {
 				// This is done by DeriveNewAccount when runCall == true
-				logging.TraceMsg(logger, "Incrementing sequence number since creates contract",
+				logger.TraceMsg("Incrementing sequence number since creates contract",
 					"tag", "sequence",
 					"account", inAcc.Address(),
 					"old_sequence", inAcc.Sequence(),
@@ -464,12 +473,12 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 
 	case *txs.NameTx:
 		// Validate input
-		inAcc, err := acm.GetMutableAccount(exe.stateCache, tx.Input.Address)
+		inAcc, err := state.GetMutableAccount(exe.stateCache, tx.Input.Address)
 		if err != nil {
 			return err
 		}
 		if inAcc == nil {
-			logging.InfoMsg(logger, "Cannot find input account",
+			logger.InfoMsg("Cannot find input account",
 				"tx_input", tx.Input)
 			return txs.ErrTxInvalidAddress
 		}
@@ -479,19 +488,19 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 		}
 		// pubKey should be present in either "inAcc" or "tx.Input"
 		if err := checkInputPubKey(inAcc, tx.Input); err != nil {
-			logging.InfoMsg(logger, "Cannot find public key for input account",
+			logger.InfoMsg("Cannot find public key for input account",
 				"tx_input", tx.Input)
 			return err
 		}
 		signBytes := acm.SignBytes(exe.chainID, tx)
 		err = validateInput(inAcc, signBytes, tx.Input)
 		if err != nil {
-			logging.InfoMsg(logger, "validateInput failed",
+			logger.InfoMsg("validateInput failed",
 				"tx_input", tx.Input, structure.ErrorKey, err)
 			return err
 		}
 		if tx.Input.Amount < tx.Fee {
-			logging.InfoMsg(logger, "Sender did not send enough to cover the fee",
+			logger.InfoMsg("Sender did not send enough to cover the fee",
 				"tx_input", tx.Input)
 			return txs.ErrTxInsufficientFunds
 		}
@@ -508,7 +517,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 		expiresIn := value / uint64(costPerBlock)
 		lastBlockHeight := exe.tip.LastBlockHeight()
 
-		logging.TraceMsg(logger, "New NameTx",
+		logger.TraceMsg("New NameTx",
 			"value", value,
 			"cost_per_block", costPerBlock,
 			"expires_in", expiresIn,
@@ -538,7 +547,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 			if value == 0 && len(tx.Data) == 0 {
 				// maybe we reward you for telling us we can delete this crap
 				// (owners if not expired, anyone if expired)
-				logging.TraceMsg(logger, "Removing NameReg entry (no value and empty data in tx requests this)",
+				logger.TraceMsg("Removing NameReg entry (no value and empty data in tx requests this)",
 					"name", entry.Name)
 				err := exe.nameRegCache.RemoveNameRegEntry(entry.Name)
 				if err != nil {
@@ -553,7 +562,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 					}
 					entry.Expires = lastBlockHeight + expiresIn
 					entry.Owner = tx.Input.Address
-					logging.TraceMsg(logger, "An old NameReg entry has expired and been reclaimed",
+					logger.TraceMsg("An old NameReg entry has expired and been reclaimed",
 						"name", entry.Name,
 						"expires_in", expiresIn,
 						"owner", entry.Owner)
@@ -567,7 +576,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 						return fmt.Errorf("names must be registered for at least %d blocks", txs.MinNameRegistrationPeriod)
 					}
 					entry.Expires = lastBlockHeight + expiresIn
-					logging.TraceMsg(logger, "Updated NameReg entry",
+					logger.TraceMsg("Updated NameReg entry",
 						"name", entry.Name,
 						"expires_in", expiresIn,
 						"old_credit", oldCredit,
@@ -591,7 +600,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 				Data:    tx.Data,
 				Expires: lastBlockHeight + expiresIn,
 			}
-			logging.TraceMsg(logger, "Creating NameReg entry",
+			logger.TraceMsg("Creating NameReg entry",
 				"name", entry.Name,
 				"expires_in", expiresIn)
 			err := exe.nameRegCache.UpdateNameRegEntry(entry)
@@ -603,7 +612,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 		// TODO: something with the value sent?
 
 		// Good!
-		logging.TraceMsg(logger, "Incrementing sequence number for NameTx",
+		logger.TraceMsg("Incrementing sequence number for NameTx",
 			"tag", "sequence",
 			"account", inAcc.Address(),
 			"old_sequence", inAcc.Sequence(),
@@ -766,12 +775,12 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 
 	case *txs.PermissionsTx:
 		// Validate input
-		inAcc, err := acm.GetMutableAccount(exe.stateCache, tx.Input.Address)
+		inAcc, err := state.GetMutableAccount(exe.stateCache, tx.Input.Address)
 		if err != nil {
 			return err
 		}
 		if inAcc == nil {
-			logging.InfoMsg(logger, "Cannot find input account",
+			logger.InfoMsg("Cannot find input account",
 				"tx_input", tx.Input)
 			return txs.ErrTxInvalidAddress
 		}
@@ -790,14 +799,14 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 
 		// pubKey should be present in either "inAcc" or "tx.Input"
 		if err := checkInputPubKey(inAcc, tx.Input); err != nil {
-			logging.InfoMsg(logger, "Cannot find public key for input account",
+			logger.InfoMsg("Cannot find public key for input account",
 				"tx_input", tx.Input)
 			return err
 		}
 		signBytes := acm.SignBytes(exe.chainID, tx)
 		err = validateInput(inAcc, signBytes, tx.Input)
 		if err != nil {
-			logging.InfoMsg(logger, "validateInput failed",
+			logger.InfoMsg("validateInput failed",
 				"tx_input", tx.Input,
 				structure.ErrorKey, err)
 			return err
@@ -805,7 +814,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 
 		value := tx.Input.Amount
 
-		logging.TraceMsg(logger, "New PermissionsTx",
+		logger.TraceMsg("New PermissionsTx",
 			"perm_args", tx.PermArgs.String())
 
 		var permAcc acm.Account
@@ -824,7 +833,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 					return perms.Base.Unset(*tx.PermArgs.Permission)
 				})
 		case permission.SetGlobal:
-			permAcc, err = mutatePermissions(exe.stateCache, permission.GlobalPermissionsAddress,
+			permAcc, err = mutatePermissions(exe.stateCache, acm.GlobalPermissionsAddress,
 				func(perms *ptypes.AccountPermissions) error {
 					return perms.Base.Set(*tx.PermArgs.Permission, *tx.PermArgs.Value)
 				})
@@ -858,7 +867,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 		}
 
 		// Good!
-		logging.TraceMsg(logger, "Incrementing sequence number for PermissionsTx",
+		logger.TraceMsg("Incrementing sequence number for PermissionsTx",
 			"tag", "sequence",
 			"account", inAcc.Address(),
 			"old_sequence", inAcc.Sequence(),
@@ -887,7 +896,7 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 	}
 }
 
-func mutatePermissions(stateReader acm.StateReader, address acm.Address,
+func mutatePermissions(stateReader state.Reader, address acm.Address,
 	mutator func(*ptypes.AccountPermissions) error) (acm.Account, error) {
 
 	account, err := stateReader.GetAccount(address)
@@ -1035,7 +1044,7 @@ func execBlock(s *State, block *txs.Block, blockPartsHeader txs.PartSetHeader) e
 // acm.PublicKey().(type) != nil, (it must be known),
 // or it must be specified in the TxInput.  If redeclared,
 // the TxInput is modified and input.PublicKey() set to nil.
-func getInputs(accountGetter acm.Getter,
+func getInputs(accountGetter state.AccountGetter,
 	ins []*txs.TxInput) (map[acm.Address]acm.MutableAccount, error) {
 
 	accounts := map[acm.Address]acm.MutableAccount{}
@@ -1044,7 +1053,7 @@ func getInputs(accountGetter acm.Getter,
 		if _, ok := accounts[in.Address]; ok {
 			return nil, txs.ErrTxDuplicateAddress
 		}
-		acc, err := acm.GetMutableAccount(accountGetter, in.Address)
+		acc, err := state.GetMutableAccount(accountGetter, in.Address)
 		if err != nil {
 			return nil, err
 		}
@@ -1060,8 +1069,8 @@ func getInputs(accountGetter acm.Getter,
 	return accounts, nil
 }
 
-func getOrMakeOutputs(accountGetter acm.Getter, accs map[acm.Address]acm.MutableAccount,
-	outs []*txs.TxOutput, logger logging_types.InfoTraceLogger) (map[acm.Address]acm.MutableAccount, error) {
+func getOrMakeOutputs(accountGetter state.AccountGetter, accs map[acm.Address]acm.MutableAccount,
+	outs []*txs.TxOutput, logger *logging.Logger) (map[acm.Address]acm.MutableAccount, error) {
 	if accs == nil {
 		accs = make(map[acm.Address]acm.MutableAccount)
 	}
@@ -1073,7 +1082,7 @@ func getOrMakeOutputs(accountGetter acm.Getter, accs map[acm.Address]acm.Mutable
 		if _, ok := accs[out.Address]; ok {
 			return nil, txs.ErrTxDuplicateAddress
 		}
-		acc, err := acm.GetMutableAccount(accountGetter, out.Address)
+		acc, err := state.GetMutableAccount(accountGetter, out.Address)
 		if err != nil {
 			return nil, err
 		}
@@ -1173,7 +1182,7 @@ func validateOutputs(outs []*txs.TxOutput) (uint64, error) {
 	return total, nil
 }
 
-func adjustByInputs(accs map[acm.Address]acm.MutableAccount, ins []*txs.TxInput, logger logging_types.InfoTraceLogger) error {
+func adjustByInputs(accs map[acm.Address]acm.MutableAccount, ins []*txs.TxInput, logger *logging.Logger) error {
 	for _, in := range ins {
 		acc := accs[in.Address]
 		if acc == nil {
@@ -1188,7 +1197,7 @@ func adjustByInputs(accs map[acm.Address]acm.MutableAccount, ins []*txs.TxInput,
 		if err != nil {
 			return err
 		}
-		logging.TraceMsg(logger, "Incrementing sequence number for SendTx (adjustByInputs)",
+		logger.TraceMsg("Incrementing sequence number for SendTx (adjustByInputs)",
 			"tag", "sequence",
 			"account", acc.Address(),
 			"old_sequence", acc.Sequence(),
@@ -1216,9 +1225,9 @@ func adjustByOutputs(accs map[acm.Address]acm.MutableAccount, outs []*txs.TxOutp
 //---------------------------------------------------------------
 
 // Get permission on an account or fall back to global value
-func HasPermission(accountGetter acm.Getter, acc acm.Account, perm ptypes.PermFlag, logger logging_types.InfoTraceLogger) bool {
+func HasPermission(accountGetter state.AccountGetter, acc acm.Account, perm ptypes.PermFlag, logger *logging.Logger) bool {
 	if perm > permission.AllPermFlags {
-		logging.InfoMsg(logger,
+		logger.InfoMsg(
 			fmt.Sprintf("HasPermission called on invalid permission 0b%b (invalid) > 0b%b (maximum) ",
 				perm, permission.AllPermFlags),
 			"invalid_permission", perm,
@@ -1226,21 +1235,21 @@ func HasPermission(accountGetter acm.Getter, acc acm.Account, perm ptypes.PermFl
 		return false
 	}
 
-	permString := permission.PermissionsString(perm)
+	permString := permission.String(perm)
 
-	v, err := acc.Permissions().Base.Compose(permission.GlobalAccountPermissions(accountGetter).Base).Get(perm)
+	v, err := acc.Permissions().Base.Compose(state.GlobalAccountPermissions(accountGetter).Base).Get(perm)
 	if err != nil {
-		logging.TraceMsg(logger, "Error obtaining permission value (will default to false/deny)",
+		logger.TraceMsg("Error obtaining permission value (will default to false/deny)",
 			"perm_flag", permString,
 			structure.ErrorKey, err)
 	}
 
 	if v {
-		logging.TraceMsg(logger, "Account has permission",
+		logger.TraceMsg("Account has permission",
 			"account_address", acc.Address,
 			"perm_flag", permString)
 	} else {
-		logging.TraceMsg(logger, "Account does not have permission",
+		logger.TraceMsg("Account does not have permission",
 			"account_address", acc.Address,
 			"perm_flag", permString)
 	}
@@ -1248,8 +1257,8 @@ func HasPermission(accountGetter acm.Getter, acc acm.Account, perm ptypes.PermFl
 }
 
 // TODO: for debug log the failed accounts
-func hasSendPermission(accountGetter acm.Getter, accs map[acm.Address]acm.MutableAccount,
-	logger logging_types.InfoTraceLogger) bool {
+func hasSendPermission(accountGetter state.AccountGetter, accs map[acm.Address]acm.MutableAccount,
+	logger *logging.Logger) bool {
 	for _, acc := range accs {
 		if !HasPermission(accountGetter, acc, permission.Send, logger) {
 			return false
@@ -1258,23 +1267,23 @@ func hasSendPermission(accountGetter acm.Getter, accs map[acm.Address]acm.Mutabl
 	return true
 }
 
-func hasNamePermission(accountGetter acm.Getter, acc acm.Account,
-	logger logging_types.InfoTraceLogger) bool {
+func hasNamePermission(accountGetter state.AccountGetter, acc acm.Account,
+	logger *logging.Logger) bool {
 	return HasPermission(accountGetter, acc, permission.Name, logger)
 }
 
-func hasCallPermission(accountGetter acm.Getter, acc acm.Account,
-	logger logging_types.InfoTraceLogger) bool {
+func hasCallPermission(accountGetter state.AccountGetter, acc acm.Account,
+	logger *logging.Logger) bool {
 	return HasPermission(accountGetter, acc, permission.Call, logger)
 }
 
-func hasCreateContractPermission(accountGetter acm.Getter, acc acm.Account,
-	logger logging_types.InfoTraceLogger) bool {
+func hasCreateContractPermission(accountGetter state.AccountGetter, acc acm.Account,
+	logger *logging.Logger) bool {
 	return HasPermission(accountGetter, acc, permission.CreateContract, logger)
 }
 
-func hasCreateAccountPermission(accountGetter acm.Getter, accs map[acm.Address]acm.MutableAccount,
-	logger logging_types.InfoTraceLogger) bool {
+func hasCreateAccountPermission(accountGetter state.AccountGetter, accs map[acm.Address]acm.MutableAccount,
+	logger *logging.Logger) bool {
 	for _, acc := range accs {
 		if !HasPermission(accountGetter, acc, permission.CreateAccount, logger) {
 			return false
@@ -1283,13 +1292,13 @@ func hasCreateAccountPermission(accountGetter acm.Getter, accs map[acm.Address]a
 	return true
 }
 
-func hasBondPermission(accountGetter acm.Getter, acc acm.Account,
-	logger logging_types.InfoTraceLogger) bool {
+func hasBondPermission(accountGetter state.AccountGetter, acc acm.Account,
+	logger *logging.Logger) bool {
 	return HasPermission(accountGetter, acc, permission.Bond, logger)
 }
 
-func hasBondOrSendPermission(accountGetter acm.Getter, accs map[acm.Address]acm.Account,
-	logger logging_types.InfoTraceLogger) bool {
+func hasBondOrSendPermission(accountGetter state.AccountGetter, accs map[acm.Address]acm.Account,
+	logger *logging.Logger) bool {
 	for _, acc := range accs {
 		if !HasPermission(accountGetter, acc, permission.Bond, logger) {
 			if !HasPermission(accountGetter, acc, permission.Send, logger) {
diff --git a/execution/execution_test.go b/execution/execution_test.go
index 47e913ce9e727a98a0a835a18a6491be7f23c13a..70c9fe37010d22db449edd90e59ba4d668311f12 100644
--- a/execution/execution_test.go
+++ b/execution/execution_test.go
@@ -23,6 +23,7 @@ import (
 	"time"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
 	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/event"
@@ -33,8 +34,9 @@ import (
 	evm_events "github.com/hyperledger/burrow/execution/evm/events"
 	"github.com/hyperledger/burrow/execution/evm/sha3"
 	"github.com/hyperledger/burrow/genesis"
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/permission/snatives"
 	ptypes "github.com/hyperledger/burrow/permission/types"
 	"github.com/hyperledger/burrow/txs"
 	"github.com/stretchr/testify/require"
@@ -111,7 +113,7 @@ x 		- roles: has, add, rm
 
 // keys
 var users = makeUsers(10)
-var logger = loggers.NewNoopInfoTraceLogger()
+var logger = logging.NewNoopLogger()
 var deterministicGenesis = genesis.NewDeterministicGenesis(34059836243380576)
 var testGenesisDoc, testPrivAccounts, _ = deterministicGenesis.
 	GenesisDoc(3, true, 1000, 1, true, 1000)
@@ -165,8 +167,8 @@ func newBaseGenDoc(globalPerm, accountPerm ptypes.AccountPermissions) genesis.Ge
 	}
 }
 
-//func getAccount(state acm.Getter, address acm.Address) acm.MutableAccount {
-//	acc, _ := acm.GetMutableAccount(state, address)
+//func getAccount(state state.AccountGetter, address acm.Address) acm.MutableAccount {
+//	acc, _ := state.GetMutableAccount(state, address)
 //	return acc
 //}
 
@@ -961,7 +963,7 @@ func TestSNativeTx(t *testing.T) {
 	snativeArgs = snativePermTestInputTx("setGlobal", users[3], permission.CreateContract, true)
 	testSNativeTxExpectFail(t, batchCommitter, snativeArgs)
 	testSNativeTxExpectPass(t, batchCommitter, permission.SetGlobal, snativeArgs)
-	acc = getAccount(batchCommitter.stateCache, permission.GlobalPermissionsAddress)
+	acc = getAccount(batchCommitter.stateCache, acm.GlobalPermissionsAddress)
 	if v, _ := acc.MutablePermissions().Base.Get(permission.CreateContract); !v {
 		t.Fatal("expected permission to be set true")
 	}
@@ -1717,8 +1719,8 @@ func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numV
 	return s0, privAccounts
 }
 
-func getAccount(state acm.Getter, address acm.Address) acm.MutableAccount {
-	acc, _ := acm.GetMutableAccount(state, address)
+func getAccount(accountGetter state.AccountGetter, address acm.Address) acm.MutableAccount {
+	acc, _ := state.GetMutableAccount(accountGetter, address)
 	return acc
 }
 
@@ -1814,15 +1816,17 @@ func testSNativeCALL(t *testing.T, expectPass bool, batchCommitter *executor, do
 	}
 }
 
-func testSNativeTxExpectFail(t *testing.T, batchCommitter *executor, snativeArgs permission.PermArgs) {
+func testSNativeTxExpectFail(t *testing.T, batchCommitter *executor, snativeArgs snatives.PermArgs) {
 	testSNativeTx(t, false, batchCommitter, 0, snativeArgs)
 }
 
-func testSNativeTxExpectPass(t *testing.T, batchCommitter *executor, perm ptypes.PermFlag, snativeArgs permission.PermArgs) {
+func testSNativeTxExpectPass(t *testing.T, batchCommitter *executor, perm ptypes.PermFlag,
+	snativeArgs snatives.PermArgs) {
 	testSNativeTx(t, true, batchCommitter, perm, snativeArgs)
 }
 
-func testSNativeTx(t *testing.T, expectPass bool, batchCommitter *executor, perm ptypes.PermFlag, snativeArgs permission.PermArgs) {
+func testSNativeTx(t *testing.T, expectPass bool, batchCommitter *executor, perm ptypes.PermFlag,
+	snativeArgs snatives.PermArgs) {
 	if expectPass {
 		acc := getAccount(batchCommitter.stateCache, users[0].Address())
 		acc.MutablePermissions().Base.Set(perm, true)
@@ -1884,16 +1888,18 @@ func snativePermTestInputCALL(name string, user acm.PrivateAccount, perm ptypes.
 	return
 }
 
-func snativePermTestInputTx(name string, user acm.PrivateAccount, perm ptypes.PermFlag, val bool) (snativeArgs permission.PermArgs) {
+func snativePermTestInputTx(name string, user acm.PrivateAccount, perm ptypes.PermFlag,
+	val bool) (snativeArgs snatives.PermArgs) {
+
 	switch name {
 	case "hasBase":
-		snativeArgs = permission.HasBaseArgs(user.Address(), perm)
+		snativeArgs = snatives.HasBaseArgs(user.Address(), perm)
 	case "unsetBase":
-		snativeArgs = permission.UnsetBaseArgs(user.Address(), perm)
+		snativeArgs = snatives.UnsetBaseArgs(user.Address(), perm)
 	case "setBase":
-		snativeArgs = permission.SetBaseArgs(user.Address(), perm, val)
+		snativeArgs = snatives.SetBaseArgs(user.Address(), perm, val)
 	case "setGlobal":
-		snativeArgs = permission.SetGlobalArgs(perm, val)
+		snativeArgs = snatives.SetGlobalArgs(perm, val)
 	}
 	return
 }
@@ -1912,14 +1918,14 @@ func snativeRoleTestInputCALL(name string, user acm.PrivateAccount,
 	return
 }
 
-func snativeRoleTestInputTx(name string, user acm.PrivateAccount, role string) (snativeArgs permission.PermArgs) {
+func snativeRoleTestInputTx(name string, user acm.PrivateAccount, role string) (snativeArgs snatives.PermArgs) {
 	switch name {
 	case "hasRole":
-		snativeArgs = permission.HasRoleArgs(user.Address(), role)
+		snativeArgs = snatives.HasRoleArgs(user.Address(), role)
 	case "addRole":
-		snativeArgs = permission.AddRoleArgs(user.Address(), role)
+		snativeArgs = snatives.AddRoleArgs(user.Address(), role)
 	case "removeRole":
-		snativeArgs = permission.RemoveRoleArgs(user.Address(), role)
+		snativeArgs = snatives.RemoveRoleArgs(user.Address(), role)
 	}
 	return
 }
diff --git a/execution/options.go b/execution/options.go
new file mode 100644
index 0000000000000000000000000000000000000000..8b6e458b890a5ce9dd1e07e24b0806634541b77f
--- /dev/null
+++ b/execution/options.go
@@ -0,0 +1,11 @@
+package execution
+
+import "github.com/hyperledger/burrow/execution/evm"
+
+type ExecutionOption func(*executor)
+
+func VMOptions(vmOptions ...func(*evm.VM)) func(*executor) {
+	return func(exe *executor) {
+		exe.vmOptions = vmOptions
+	}
+}
diff --git a/execution/state.go b/execution/state.go
index 7385267b3be6395b0b17dd6decddb9a4b0d4b01a..73fb51df903ab78f9dfaa3cf77375a270c317cdd 100644
--- a/execution/state.go
+++ b/execution/state.go
@@ -22,10 +22,10 @@ import (
 	"time"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/genesis"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-	"github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/logging"
 	ptypes "github.com/hyperledger/burrow/permission"
 	"github.com/hyperledger/burrow/txs"
 	"github.com/tendermint/go-wire"
@@ -52,9 +52,9 @@ var (
 )
 
 // Implements account and blockchain state
-var _ acm.Updater = &State{}
-var _ acm.StateIterable = &State{}
-var _ acm.StateWriter = &State{}
+var _ state.AccountUpdater = &State{}
+var _ state.Iterable = &State{}
+var _ state.Writer = &State{}
 
 type State struct {
 	sync.RWMutex
@@ -62,7 +62,7 @@ type State struct {
 	version uint64
 	// TODO:
 	tree   *iavl.VersionedTree
-	logger logging_types.InfoTraceLogger
+	logger *logging.Logger
 }
 
 func NewState(db dbm.DB) *State {
@@ -112,7 +112,7 @@ func MakeGenesisState(db dbm.DB, genesisDoc *genesis.GenesisDoc) (*State, error)
 	globalPerms.Base.SetBit = ptypes.AllPermFlags
 
 	permsAcc := &acm.ConcreteAccount{
-		Address:     permission.GlobalPermissionsAddress,
+		Address:     acm.GlobalPermissionsAddress,
 		Balance:     1337,
 		Permissions: globalPerms,
 	}
diff --git a/execution/state_test.go b/execution/state_test.go
index fb310574d557ffdb4b96abc0b07631678859c176..6ad9c32192ec5efc1cec705138a5ef83f2cb400d 100644
--- a/execution/state_test.go
+++ b/execution/state_test.go
@@ -18,6 +18,8 @@ import (
 	"testing"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/permission"
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"github.com/tendermint/tmlibs/db"
 )
@@ -25,8 +27,12 @@ import (
 func TestState_UpdateAccount(t *testing.T) {
 	state := NewState(db.NewMemDB())
 	account := acm.NewConcreteAccountFromSecret("Foo").MutableAccount()
-	account.SetStorageRoot([]byte{2, 3, 4})
-	state.UpdateAccount(account)
-	err := state.Save()
+	account.MutablePermissions().Base.Perms = permission.SetGlobal | permission.HasRole
+	err := state.UpdateAccount(account)
+	err = state.Save()
+
+	require.NoError(t, err)
+	accountOut, err := state.GetAccount(account.Address())
 	require.NoError(t, err)
+	assert.Equal(t, account, accountOut)
 }
diff --git a/execution/transactor.go b/execution/transactor.go
index f54cd02f60a3f56029e994ab5f699032cae206dc..9050949dc451ab537b6ee653e76f80636e659eea 100644
--- a/execution/transactor.go
+++ b/execution/transactor.go
@@ -20,7 +20,10 @@ import (
 	"sync"
 	"time"
 
+	"runtime/debug"
+
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/consensus/tendermint/codes"
@@ -30,7 +33,6 @@ import (
 	evm_events "github.com/hyperledger/burrow/execution/evm/events"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/txs"
 	abci_types "github.com/tendermint/abci/types"
 	"github.com/tendermint/go-wire"
@@ -60,17 +62,17 @@ type Transactor interface {
 type transactor struct {
 	txMtx            sync.Mutex
 	blockchain       blockchain.Blockchain
-	state            acm.StateIterable
+	state            state.Iterable
 	eventEmitter     event.Emitter
 	broadcastTxAsync func(tx txs.Tx, callback func(res *abci_types.Response)) error
-	logger           logging_types.InfoTraceLogger
+	logger           *logging.Logger
 }
 
 var _ Transactor = &transactor{}
 
-func NewTransactor(blockchain blockchain.Blockchain, state acm.StateIterable, eventEmitter event.Emitter,
+func NewTransactor(blockchain blockchain.Blockchain, state state.Iterable, eventEmitter event.Emitter,
 	broadcastTxAsync func(tx txs.Tx, callback func(res *abci_types.Response)) error,
-	logger logging_types.InfoTraceLogger) *transactor {
+	logger *logging.Logger) *transactor {
 
 	return &transactor{
 		blockchain:       blockchain,
@@ -83,14 +85,14 @@ func NewTransactor(blockchain blockchain.Blockchain, state acm.StateIterable, ev
 
 // Run a contract's code on an isolated and unpersisted state
 // Cannot be used to create new contracts
-func (trans *transactor) Call(fromAddress, toAddress acm.Address, data []byte) (*Call, error) {
+func (trans *transactor) Call(fromAddress, toAddress acm.Address, data []byte) (call *Call, err error) {
 	if evm.RegisteredNativeContract(toAddress.Word256()) {
 		return nil, fmt.Errorf("attempt to call native contract at address "+
 			"%X, but native contracts can not be called directly. Use a deployed "+
 			"contract that calls the native function instead", toAddress)
 	}
 	// This was being run against CheckTx cache, need to understand the reasoning
-	callee, err := acm.GetMutableAccount(trans.state, toAddress)
+	callee, err := state.GetMutableAccount(trans.state, toAddress)
 	if err != nil {
 		return nil, err
 	}
@@ -98,14 +100,18 @@ func (trans *transactor) Call(fromAddress, toAddress acm.Address, data []byte) (
 		return nil, fmt.Errorf("account %s does not exist", toAddress)
 	}
 	caller := acm.ConcreteAccount{Address: fromAddress}.MutableAccount()
-	txCache := acm.NewStateCache(trans.state)
+	txCache := state.NewCache(trans.state)
 	params := vmParams(trans.blockchain)
 
-	vmach := evm.NewVM(txCache, evm.DefaultDynamicMemoryProvider, params, caller.Address(), nil,
-		logging.WithScope(trans.logger, "Call"))
+	vmach := evm.NewVM(txCache, params, caller.Address(), nil, trans.logger.WithScope("Call"))
 	vmach.SetPublisher(trans.eventEmitter)
 
 	gas := params.GasLimit
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("panic from VM in simulated call: %v\n%s", r, debug.Stack())
+		}
+	}()
 	ret, err := vmach.Call(caller, callee, callee.Code(), data, 0, &gas)
 	if err != nil {
 		return nil, err
@@ -120,11 +126,10 @@ func (trans *transactor) CallCode(fromAddress acm.Address, code, data []byte) (*
 	// This was being run against CheckTx cache, need to understand the reasoning
 	callee := acm.ConcreteAccount{Address: fromAddress}.MutableAccount()
 	caller := acm.ConcreteAccount{Address: fromAddress}.MutableAccount()
-	txCache := acm.NewStateCache(trans.state)
+	txCache := state.NewCache(trans.state)
 	params := vmParams(trans.blockchain)
 
-	vmach := evm.NewVM(txCache, evm.DefaultDynamicMemoryProvider, params, caller.Address(), nil,
-		logging.WithScope(trans.logger, "CallCode"))
+	vmach := evm.NewVM(txCache, params, caller.Address(), nil, trans.logger.WithScope("CallCode"))
 	gas := params.GasLimit
 	ret, err := vmach.Call(caller, callee, code, data, 0, &gas)
 	if err != nil {
@@ -140,7 +145,7 @@ func (trans *transactor) BroadcastTxAsync(tx txs.Tx, callback func(res *abci_typ
 
 // Broadcast a transaction.
 func (trans *transactor) BroadcastTx(tx txs.Tx) (*txs.Receipt, error) {
-	trans.logger.Trace("method", "BroadcastTx",
+	trans.logger.Trace.Log("method", "BroadcastTx",
 		"tx_hash", tx.Hash(trans.blockchain.ChainID()),
 		"tx", tx.String())
 	responseCh := make(chan *abci_types.Response, 1)
diff --git a/keys/integration/key_client_test.go b/keys/integration/key_client_test.go
index f165074bc0a99f8115abd956dab5e51622234ecc..83f5d4b6282521292a2326b1d76ee41599b53d47 100644
--- a/keys/integration/key_client_test.go
+++ b/keys/integration/key_client_test.go
@@ -13,13 +13,13 @@ import (
 
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/keys"
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
 //var logger, _ = lifecycle.NewStdErrLogger()
-var logger = loggers.NewNoopInfoTraceLogger()
+var logger = logging.NewNoopLogger()
 
 const monaxKeysBin = "monax-keys"
 const keysHost = "localhost"
diff --git a/keys/key_client.go b/keys/key_client.go
index e53a30ba7093f5741daa4d30f3ae8fca4ca90674..c70cb4aecca9af987937d6f50675c5def19f4bce 100644
--- a/keys/key_client.go
+++ b/keys/key_client.go
@@ -20,7 +20,6 @@ import (
 
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 )
 
 type KeyClient interface {
@@ -61,7 +60,7 @@ var _ KeyClient = (*keyClient)(nil)
 
 type keyClient struct {
 	requester Requester
-	logger    logging_types.InfoTraceLogger
+	logger    *logging.Logger
 }
 
 type signer struct {
@@ -71,8 +70,8 @@ type signer struct {
 
 // keyClient.New returns a new monax-keys client for provided rpc location
 // Monax-keys connects over http request-responses
-func NewKeyClient(rpcAddress string, logger logging_types.InfoTraceLogger) *keyClient {
-	logger = logging.WithScope(logger, "NewKeyClient")
+func NewKeyClient(rpcAddress string, logger *logging.Logger) *keyClient {
+	logger = logger.WithScope("NewKeyClient")
 	return &keyClient{
 		requester: DefaultRequester(rpcAddress, logger),
 		logger:    logger,
diff --git a/keys/key_client_util.go b/keys/key_client_util.go
index ea30faef9a2cc317a099835d18219af1173e74fa..89a41a366d359b1fc2cc90377fa20f5c9e004e08 100644
--- a/keys/key_client_util.go
+++ b/keys/key_client_util.go
@@ -22,7 +22,6 @@ import (
 	"net/http"
 
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 )
 
 // Monax-Keys server connects over http request-response structures
@@ -34,14 +33,14 @@ type HTTPResponse struct {
 
 type Requester func(method string, args map[string]string) (response string, err error)
 
-func DefaultRequester(rpcAddress string, logger logging_types.InfoTraceLogger) Requester {
+func DefaultRequester(rpcAddress string, logger *logging.Logger) Requester {
 	return func(method string, args map[string]string) (string, error) {
 		body, err := json.Marshal(args)
 		if err != nil {
 			return "", err
 		}
 		endpoint := fmt.Sprintf("%s/%s", rpcAddress, method)
-		logging.TraceMsg(logger, "Sending request to key server",
+		logger.TraceMsg("Sending request to key server",
 			"key_server_endpoint", endpoint,
 			"request_body", string(body),
 		)
@@ -57,7 +56,7 @@ func DefaultRequester(rpcAddress string, logger logging_types.InfoTraceLogger) R
 		if res.Error != "" {
 			return "", fmt.Errorf("response error when calling monax-keys at %s: %s", endpoint, res.Error)
 		}
-		logging.TraceMsg(logger, "Received response from key server",
+		logger.TraceMsg("Received response from key server",
 			"endpoint", endpoint,
 			"request_body", string(body),
 			"response", res,
diff --git a/logging/adapters/stdlib/capture.go b/logging/adapters/stdlib/capture.go
index 599a19a70aa36bc2107029ef12df1075055726c3..07512b75da0db9826fb82fbb127c02a78b8f034a 100644
--- a/logging/adapters/stdlib/capture.go
+++ b/logging/adapters/stdlib/capture.go
@@ -19,22 +19,21 @@ import (
 	"log"
 
 	kitlog "github.com/go-kit/kit/log"
-	"github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/logging"
 )
 
-func Capture(stdLibLogger log.Logger,
-	logger types.InfoTraceLogger) io.Writer {
+func Capture(stdLibLogger log.Logger, logger *logging.Logger) io.Writer {
 	adapter := newAdapter(logger)
 	stdLibLogger.SetOutput(adapter)
 	return adapter
 }
 
-func CaptureRootLogger(logger types.InfoTraceLogger) io.Writer {
+func CaptureRootLogger(logger *logging.Logger) io.Writer {
 	adapter := newAdapter(logger)
 	log.SetOutput(adapter)
 	return adapter
 }
 
-func newAdapter(logger types.InfoTraceLogger) io.Writer {
-	return kitlog.NewStdlibAdapter(logger)
+func newAdapter(logger *logging.Logger) io.Writer {
+	return kitlog.NewStdlibAdapter(logger.Trace)
 }
diff --git a/logging/config/config.go b/logging/config/config.go
index 9eba4085bbb8a47a0cabd45f003e548690541a8d..dca01d2ed6049399c11a7f1d251c9a71afa874e8 100644
--- a/logging/config/config.go
+++ b/logging/config/config.go
@@ -9,10 +9,12 @@ import (
 	"encoding/json"
 
 	"github.com/BurntSushi/toml"
+	"github.com/hyperledger/burrow/logging/loggers"
 )
 
 type LoggingConfig struct {
-	RootSink *SinkConfig `toml:",omitempty"`
+	RootSink     *SinkConfig `toml:",omitempty"`
+	ExcludeTrace bool
 }
 
 // For encoding a top-level '[logging]' TOML table
@@ -22,7 +24,7 @@ type LoggingConfigWrapper struct {
 
 func DefaultNodeLoggingConfig() *LoggingConfig {
 	return &LoggingConfig{
-		RootSink: Sink().SetOutput(StderrOutput()),
+		RootSink: Sink().SetOutput(StderrOutput().SetFormat(loggers.JSONFormat)),
 	}
 }
 
@@ -53,28 +55,6 @@ func (lc *LoggingConfig) JSONString() string {
 	return JSONString(lc)
 }
 
-func LoggingConfigFromMap(loggingRootMap map[string]interface{}) (*LoggingConfig, error) {
-	lc := new(LoggingConfig)
-	buf := new(bytes.Buffer)
-	enc := toml.NewEncoder(buf)
-	// TODO: [Silas] consider using strongly typed config/struct mapping everywhere
-	// (!! unfortunately the way we are using viper
-	// to pass around a untyped bag of config means that we don't get keys mapped
-	// according to their metadata `toml:"Name"` tags. So we are re-encoding to toml
-	// and then decoding into the strongly type struct as a work-around)
-	// Encode the map back to TOML
-	err := enc.Encode(loggingRootMap)
-	if err != nil {
-		return nil, err
-	}
-	// Decode into struct into the LoggingConfig struct
-	_, err = toml.Decode(buf.String(), lc)
-	if err != nil {
-		return nil, err
-	}
-	return lc, nil
-}
-
 func TOMLString(v interface{}) string {
 	buf := new(bytes.Buffer)
 	encoder := toml.NewEncoder(buf)
diff --git a/logging/config/presets/instructions.go b/logging/config/presets/instructions.go
index 2844ae8bc19f8453033e536c611d3e8039580ec9..9077d9e8242dc19423e5f1faf913ca97a9e650ec 100644
--- a/logging/config/presets/instructions.go
+++ b/logging/config/presets/instructions.go
@@ -6,7 +6,6 @@ import (
 	"github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/logging/types"
 )
 
 // Function to generate part of a tree of Sinks (e.g. append a single child node, or an entire subtree).
@@ -64,7 +63,7 @@ var instructions = []Instruction{
 			return push(stack,
 					config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)),
 					config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch,
-						structure.ChannelKey, types.InfoChannelName)),
+						structure.ChannelKey, structure.InfoChannelName)),
 					config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches,
 						structure.ComponentKey, "Tendermint",
 						"module", "p2p",
@@ -88,7 +87,7 @@ var instructions = []Instruction{
 		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
 			sink := peek(stack)
 			ensureFilter(sink)
-			sink.Transform.FilterConfig.AddPredicate(structure.ChannelKey, types.InfoChannelName)
+			sink.Transform.FilterConfig.AddPredicate(structure.ChannelKey, structure.InfoChannelName)
 			return stack, ops, nil
 		},
 	},
diff --git a/logging/config/presets/instructions_test.go b/logging/config/presets/instructions_test.go
index c1da2f87b96d1c4eb84afe20de2da7a97a4f9dfb..adbfe1b0a5fd4bc6863c372c4a61a60a33f0f25c 100644
--- a/logging/config/presets/instructions_test.go
+++ b/logging/config/presets/instructions_test.go
@@ -6,7 +6,6 @@ import (
 	"github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/logging/types"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -16,11 +15,11 @@ func TestBuildSinkConfig(t *testing.T) {
 	require.NoError(t, err)
 	expectedSink := config.Sink().
 		SetTransform(config.FilterTransform(config.IncludeWhenAnyMatches,
-			structure.ChannelKey, types.InfoChannelName)).SetOutput(config.StdoutOutput().SetFormat(loggers.TerminalFormat)).AddSinks(
+			structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StdoutOutput().SetFormat(loggers.TerminalFormat)).AddSinks(
 		config.Sink().SetTransform(config.FilterTransform(config.NoFilterMode,
-			structure.ChannelKey, types.InfoChannelName)).SetOutput(config.StderrOutput()).AddSinks(
+			structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StderrOutput()).AddSinks(
 			config.Sink().SetTransform(config.FilterTransform(config.NoFilterMode,
-				structure.ChannelKey, types.InfoChannelName)).SetOutput(config.StdoutOutput())))
+				structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StdoutOutput())))
 
 	//fmt.Println(config.JSONString(expectedSink), "\n", config.JSONString(builtSink))
 	assert.Equal(t, config.JSONString(expectedSink), config.JSONString(builtSink))
@@ -32,7 +31,7 @@ func TestMinimalPreset(t *testing.T) {
 	expectedSink := config.Sink().
 		AddSinks(config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)).
 			AddSinks(config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch,
-				structure.ChannelKey, types.InfoChannelName)).
+				structure.ChannelKey, structure.InfoChannelName)).
 				AddSinks(config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches,
 					structure.ComponentKey, "Tendermint",
 					"module", "p2p",
diff --git a/logging/config/sinks.go b/logging/config/sinks.go
index 169e886f68fa075bcd0d34fc54b792f609c7d95b..aa30a69e1e07172d6e9751b7a21cd8515ded60ed 100644
--- a/logging/config/sinks.go
+++ b/logging/config/sinks.go
@@ -6,7 +6,6 @@ import (
 
 	"github.com/eapache/channels"
 	kitlog "github.com/go-kit/kit/log"
-	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/logging/structure"
 )
@@ -32,9 +31,10 @@ const (
 	// Remove key-val pairs from each log line
 	Prune transformType = "prune"
 	// Add key value pairs to each log line
-	Label   transformType = "label"
-	Capture transformType = "capture"
-	Sort    transformType = "sort"
+	Label     transformType = "label"
+	Capture   transformType = "capture"
+	Sort      transformType = "sort"
+	Vectorise transformType = "vectorise"
 
 	// TODO [Silas]: add 'flush on exit' transform which flushes the buffer of
 	// CaptureLogger to its OutputLogger a non-passthrough capture when an exit
@@ -199,6 +199,8 @@ func FileOutput(path string) *OutputConfig {
 	}
 }
 
+// Transforms
+
 func CaptureTransform(name string, bufferCap int, passthrough bool) *TransformConfig {
 	return &TransformConfig{
 		TransformType: Capture,
@@ -275,6 +277,12 @@ func SortTransform(keys ...string) *TransformConfig {
 	}
 }
 
+func VectoriseTransform() *TransformConfig {
+	return &TransformConfig{
+		TransformType: Vectorise,
+	}
+}
+
 // Logger formation
 func (sinkConfig *SinkConfig) BuildLogger() (kitlog.Logger, map[string]*loggers.CaptureLogger, error) {
 	return BuildLoggerFromSinkConfig(sinkConfig, make(map[string]*loggers.CaptureLogger))
@@ -404,6 +412,8 @@ func BuildTransformLogger(transformConfig *TransformConfig, captures map[string]
 			return nil, nil, fmt.Errorf("sort transform specified but no SortConfig provided")
 		}
 		return loggers.SortLogger(outputLogger, transformConfig.SortConfig.Keys...), captures, nil
+	case Vectorise:
+		return loggers.VectorValuedLogger(outputLogger), captures, nil
 	default:
 		return nil, captures, fmt.Errorf("could not build logger for transform: '%s'", transformConfig.TransformType)
 	}
@@ -411,7 +421,7 @@ func BuildTransformLogger(transformConfig *TransformConfig, captures map[string]
 
 func signalPassthroughLogger(ifSignalLogger kitlog.Logger, otherwiseLogger kitlog.Logger) kitlog.Logger {
 	return kitlog.LoggerFunc(func(keyvals ...interface{}) error {
-		if logging.Signal(keyvals) != "" {
+		if structure.Signal(keyvals) != "" {
 			return ifSignalLogger.Log(keyvals...)
 		}
 		return otherwiseLogger.Log(keyvals...)
diff --git a/logging/convention.go b/logging/convention.go
deleted file mode 100644
index 65dc2e5b98106caa86768139dbf509e0c321e92d..0000000000000000000000000000000000000000
--- a/logging/convention.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2017 Monax Industries Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package logging
-
-import (
-	kitlog "github.com/go-kit/kit/log"
-	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/logging/types"
-)
-
-// Helper functions for InfoTraceLoggers, sort of extension methods to loggers
-// to centralise and establish logging conventions on top of in with the base
-// logging interface
-
-// Record structured Info log line with a message
-func InfoMsg(logger types.InfoTraceLogger, message string, keyvals ...interface{}) error {
-	return Msg(kitlog.LoggerFunc(logger.Info), message, keyvals...)
-}
-
-// Record structured Trace log line with a message
-func TraceMsg(logger types.InfoTraceLogger, message string, keyvals ...interface{}) error {
-	return Msg(kitlog.LoggerFunc(logger.Trace), message, keyvals...)
-}
-
-// Establish or extend the scope of this logger by appending scopeName to the Scope vector.
-// Like With the logging scope is append only but can be used to provide parenthetical scopes by hanging on to the
-// parent scope and using once the scope has been exited. The scope mechanism does is agnostic to the type of scope
-// so can be used to identify certain segments of the call stack, a lexical scope, or any other nested scope.
-func WithScope(logger types.InfoTraceLogger, scopeName string) types.InfoTraceLogger {
-	// InfoTraceLogger will collapse successive (ScopeKey, scopeName) pairs into a vector in the order which they appear
-	return logger.With(structure.ScopeKey, scopeName)
-}
-
-// Record a structured log line with a message
-func Msg(logger kitlog.Logger, message string, keyvals ...interface{}) error {
-	prepended := structure.CopyPrepend(keyvals, structure.MessageKey, message)
-	return logger.Log(prepended...)
-}
-
-// Sends the sync signal which causes any syncing loggers to sync.
-// loggers receiving the signal should drop the signal logline from output
-func Sync(logger kitlog.Logger) error {
-	return logger.Log(structure.SignalKey, structure.SyncSignal)
-}
-
-// Tried to interpret the logline as a signal by matching the last key-value pair as a signal, returns empty string if
-// no match
-func Signal(keyvals []interface{}) string {
-	last := len(keyvals) - 1
-	if last > 0 && keyvals[last-1] == structure.SignalKey {
-		signal, ok := keyvals[last].(string)
-		if ok {
-			return signal
-		}
-	}
-	return ""
-}
diff --git a/logging/lifecycle/lifecycle.go b/logging/lifecycle/lifecycle.go
index e68a26021c129b918d8ea1b3d142d6fe441e6341..d130904c2e5b9f2bf3d21aaadd1edda29409eadb 100644
--- a/logging/lifecycle/lifecycle.go
+++ b/logging/lifecycle/lifecycle.go
@@ -30,7 +30,6 @@ import (
 	"github.com/eapache/channels"
 	kitlog "github.com/go-kit/kit/log"
 	"github.com/hyperledger/burrow/logging"
-	"github.com/hyperledger/burrow/logging/types"
 	"github.com/streadway/simpleuuid"
 )
 
@@ -38,8 +37,8 @@ import (
 // to set up their root logger and capture any other logging output.
 
 // Obtain a logger from a LoggingConfig
-func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (types.InfoTraceLogger, error) {
-	var logger types.InfoTraceLogger
+func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (*logging.Logger, error) {
+	var logger *logging.Logger
 	var errCh channels.Channel
 	var err error
 	if loggingConfig == nil {
@@ -48,11 +47,14 @@ func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (types.Info
 			return nil, err
 		}
 	} else {
-		outputLogger, err := infoTraceLoggerFromLoggingConfig(loggingConfig)
+		outputLogger, err := loggerFromLoggingConfig(loggingConfig)
 		if err != nil {
 			return nil, err
 		}
 		logger, errCh = NewLogger(outputLogger)
+		if loggingConfig.ExcludeTrace {
+			logger.Trace = kitlog.NewNopLogger()
+		}
 	}
 	go func() {
 		err := <-errCh.Out()
@@ -66,9 +68,8 @@ func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (types.Info
 
 // Hot swap logging config by replacing output loggers of passed InfoTraceLogger
 // with those built from loggingConfig
-func SwapOutputLoggersFromLoggingConfig(logger types.InfoTraceLogger,
-	loggingConfig *config.LoggingConfig) error {
-	outputLogger, err := infoTraceLoggerFromLoggingConfig(loggingConfig)
+func SwapOutputLoggersFromLoggingConfig(logger *logging.Logger, loggingConfig *config.LoggingConfig) error {
+	outputLogger, err := loggerFromLoggingConfig(loggingConfig)
 	if err != nil {
 		return err
 	}
@@ -76,38 +77,38 @@ func SwapOutputLoggersFromLoggingConfig(logger types.InfoTraceLogger,
 	return nil
 }
 
-func NewStdErrLogger() (types.InfoTraceLogger, channels.Channel, error) {
-	logger, err := loggers.NewStreamLogger(os.Stderr, loggers.TerminalFormat)
+func NewStdErrLogger() (*logging.Logger, channels.Channel, error) {
+	outputLogger, err := loggers.NewStreamLogger(os.Stderr, loggers.TerminalFormat)
 	if err != nil {
 		return nil, nil, err
 	}
-	itLogger, errCh := NewLogger(logger)
-	return itLogger, errCh, nil
+	logger, errCh := NewLogger(outputLogger)
+	return logger, errCh, nil
 }
 
 // Provided a standard logger that outputs to the supplied underlying outputLogger
-func NewLogger(outputLogger kitlog.Logger) (types.InfoTraceLogger, channels.Channel) {
-	infoTraceLogger, errCh := loggers.NewInfoTraceLogger(outputLogger)
+func NewLogger(outputLogger kitlog.Logger) (*logging.Logger, channels.Channel) {
+	logger, errCh := logging.NewLogger(outputLogger)
 	// Create a random ID based on start time
 	uuid, _ := simpleuuid.NewTime(time.Now())
 	var runId string
 	if uuid != nil {
 		runId = uuid.String()
 	}
-	return logging.WithMetadata(infoTraceLogger.With(structure.RunId, runId)), errCh
+	return logger.With(structure.RunId, runId), errCh
 }
 
-func JustLogger(logger types.InfoTraceLogger, _ channels.Channel) types.InfoTraceLogger {
+func JustLogger(logger *logging.Logger, _ channels.Channel) *logging.Logger {
 	return logger
 }
 
-func CaptureStdlibLogOutput(infoTraceLogger types.InfoTraceLogger) {
+func CaptureStdlibLogOutput(infoTraceLogger *logging.Logger) {
 	stdlib.CaptureRootLogger(infoTraceLogger.
 		With(structure.CapturedLoggingSourceKey, "stdlib_log"))
 }
 
 // Helpers
-func infoTraceLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (kitlog.Logger, error) {
+func loggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (kitlog.Logger, error) {
 	outputLogger, _, err := loggingConfig.RootSink.BuildLogger()
 	if err != nil {
 		return nil, err
diff --git a/logging/lifecycle/lifecycle_test.go b/logging/lifecycle/lifecycle_test.go
index c38e6491406a376edd1c962ecf89aadf2405bff9..91ae8a16cbf995a751657ffe4074cc5f818dc968 100644
--- a/logging/lifecycle/lifecycle_test.go
+++ b/logging/lifecycle/lifecycle_test.go
@@ -13,7 +13,7 @@ func TestNewLoggerFromLoggingConfig(t *testing.T) {
 	reader := CaptureStderr(t, func() {
 		logger, err := NewLoggerFromLoggingConfig(nil)
 		assert.NoError(t, err)
-		logger.Info("Quick", "Test")
+		logger.Info.Log("Quick", "Test")
 	})
 	line, _, err := reader.ReadLine()
 	assert.NoError(t, err)
diff --git a/logging/logger.go b/logging/logger.go
new file mode 100644
index 0000000000000000000000000000000000000000..51346c4f18d34ebd7c60603ee562afbf724c2509
--- /dev/null
+++ b/logging/logger.go
@@ -0,0 +1,149 @@
+// Copyright 2017 Monax Industries Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package logging
+
+import (
+	"github.com/eapache/channels"
+	kitlog "github.com/go-kit/kit/log"
+	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging/structure"
+)
+
+// InfoTraceLogger maintains provides two logging 'channels' that are interlaced
+// to provide a coarse grained filter to distinguish human-consumable 'Info'
+// messages and execution level 'Trace' messages.
+type Logger struct {
+	// Send a log message to the Info channel, formed of a sequence of key value
+	// pairs. Info messages should be operationally interesting to a human who is
+	// monitoring the logs. But not necessarily a human who is trying to
+	// understand or debug the system. Any handled errors or warnings should be
+	// sent to the Info channel (where you may wish to tag them with a suitable
+	// key-value pair to categorise them as such).
+	Info kitlog.Logger
+	// Send an log message to the Trace channel, formed of a sequence of key-value
+	// pairs. Trace messages can be used for any state change in the system that
+	// may be of interest to a machine consumer or a human who is trying to debug
+	// the system or trying to understand the system in detail. If the messages
+	// are very point-like and contain little structure, consider using a metric
+	// instead.
+	Trace  kitlog.Logger
+	Output *kitlog.SwapLogger
+}
+
+// Create an InfoTraceLogger by passing the initial outputLogger.
+func NewLogger(outputLogger kitlog.Logger) (*Logger, channels.Channel) {
+	// We will never halt the progress of a log emitter. If log output takes too
+	// long will start dropping log lines by using a ring buffer.
+	swapLogger := new(kitlog.SwapLogger)
+	swapLogger.Swap(outputLogger)
+	wrappedOutputLogger, errCh := wrapOutputLogger(swapLogger)
+	return &Logger{
+		Output: swapLogger,
+		// logging contexts
+		Info: kitlog.With(wrappedOutputLogger,
+			structure.ChannelKey, structure.InfoChannelName,
+		),
+		Trace: kitlog.With(wrappedOutputLogger,
+			structure.ChannelKey, structure.TraceChannelName,
+		),
+	}, errCh
+}
+
+func NewNoopLogger() *Logger {
+	return &Logger{
+		Info:   kitlog.NewNopLogger(),
+		Trace:  kitlog.NewNopLogger(),
+		Output: new(kitlog.SwapLogger),
+	}
+}
+
+// A logging context (see go-kit log's Context). Takes a sequence key values
+// via With or WithPrefix and ensures future calls to log will have those
+// contextual values appended to the call to an underlying logger.
+// Values can be dynamic by passing an instance of the kitlog.Valuer interface
+// This provides an interface version of the kitlog.Context struct to be used
+// For implementations that wrap a kitlog.Context. In addition it makes no
+// assumption about the name or signature of the logging method(s).
+// See InfoTraceLogger
+func (l *Logger) With(keyvals ...interface{}) *Logger {
+	return &Logger{
+		Output: l.Output,
+		Info:   kitlog.With(l.Info, keyvals...),
+		Trace:  kitlog.With(l.Trace, keyvals...),
+	}
+}
+
+// Establish a context on the Info channel keeping Trace the same
+func (l *Logger) WithInfo(keyvals ...interface{}) *Logger {
+	return &Logger{
+		Output: l.Output,
+		Info:   kitlog.With(l.Info, keyvals...),
+		Trace:  l.Trace,
+	}
+}
+
+// Establish a context on the Trace channel keeping Info the same
+func (l *Logger) WithTrace(keyvals ...interface{}) *Logger {
+	return &Logger{
+		Output: l.Output,
+		Info:   l.Info,
+		Trace:  kitlog.With(l.Trace, keyvals...),
+	}
+}
+
+func (l *Logger) WithPrefix(keyvals ...interface{}) *Logger {
+	return &Logger{
+		Output: l.Output,
+		Info:   kitlog.WithPrefix(l.Info, keyvals...),
+		Trace:  kitlog.WithPrefix(l.Trace, keyvals...),
+	}
+}
+
+// Hot swap the underlying outputLogger with another one to re-route messages
+func (l *Logger) SwapOutput(infoLogger kitlog.Logger) {
+	l.Output.Swap(infoLogger)
+}
+
+// Record structured Info lo`g line with a message
+func (l *Logger) InfoMsg(message string, keyvals ...interface{}) error {
+	return Msg(l.Info, message, keyvals...)
+}
+
+// Record structured Trace log line with a message
+func (l *Logger) TraceMsg(message string, keyvals ...interface{}) error {
+	return Msg(l.Trace, message, keyvals...)
+}
+
+// Establish or extend the scope of this logger by appending scopeName to the Scope vector.
+// Like With the logging scope is append only but can be used to provide parenthetical scopes by hanging on to the
+// parent scope and using once the scope has been exited. The scope mechanism does is agnostic to the type of scope
+// so can be used to identify certain segments of the call stack, a lexical scope, or any other nested scope.
+func (l *Logger) WithScope(scopeName string) *Logger {
+	// InfoTraceLogger will collapse successive (ScopeKey, scopeName) pairs into a vector in the order which they appear
+	return l.With(structure.ScopeKey, scopeName)
+}
+
+// Record a structured log line with a message
+func Msg(logger kitlog.Logger, message string, keyvals ...interface{}) error {
+	prepended := structure.CopyPrepend(keyvals, structure.MessageKey, message)
+	return logger.Log(prepended...)
+}
+
+// Wrap the output loggers with a a set of standard transforms, a non-blocking
+// ChannelLogger and an outer context
+func wrapOutputLogger(outputLogger kitlog.Logger) (kitlog.Logger, channels.Channel) {
+	//return loggers.NonBlockingLogger(loggers.BurrowFormatLogger(outputLogger))
+	return loggers.BurrowFormatLogger(outputLogger), channels.NewDeadChannel()
+}
diff --git a/logging/loggers/info_trace_logger_test.go b/logging/logger_test.go
similarity index 82%
rename from logging/loggers/info_trace_logger_test.go
rename to logging/logger_test.go
index 2356748dc102e873c86d02a327c0da1c0fa984cf..05c0858c1764171c1776ca9be766e5aed6ab3c7f 100644
--- a/logging/loggers/info_trace_logger_test.go
+++ b/logging/logger_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package loggers
+package logging
 
 import (
 	"os"
@@ -23,11 +23,11 @@ import (
 
 func TestLogger(t *testing.T) {
 	stderrLogger := kitlog.NewLogfmtLogger(os.Stderr)
-	logger, _ := NewInfoTraceLogger(stderrLogger)
-	logger.Trace("hello", "barry")
+	logger, _ := NewLogger(stderrLogger)
+	logger.Trace.Log("hello", "barry")
 }
 
 func TestNewNoopInfoTraceLogger(t *testing.T) {
-	logger := NewNoopInfoTraceLogger()
-	logger.Trace("goodbye", "trevor")
+	logger := NewNoopLogger()
+	logger.Trace.Log("goodbye", "trevor")
 }
diff --git a/logging/loggers/burrow_format_logger.go b/logging/loggers/burrow_format_logger.go
index 51f025e73434f2cfdd4c46a146f503dc30acbd72..f32d0933de7c18fd8abe6d640f529460158253a1 100644
--- a/logging/loggers/burrow_format_logger.go
+++ b/logging/loggers/burrow_format_logger.go
@@ -45,6 +45,8 @@ func (bfl *burrowFormatLogger) Log(keyvals ...interface{}) error {
 		func(key interface{}, value interface{}) (interface{}, interface{}) {
 			switch v := value.(type) {
 			case string:
+			case fmt.Stringer:
+				value = v.String()
 			case []byte:
 				value = fmt.Sprintf("%X", v)
 			case time.Time:
diff --git a/logging/loggers/capture_logger.go b/logging/loggers/capture_logger.go
index e195c3a454c24fdd9d8056cf937197a27642b7a5..a470582afd0093fe7bdfe53b87ff7de951da92a4 100644
--- a/logging/loggers/capture_logger.go
+++ b/logging/loggers/capture_logger.go
@@ -16,13 +16,12 @@ type CaptureLogger struct {
 
 var _ kitlog.Logger = (*CaptureLogger)(nil)
 
-// Capture logger captures output set to it into a buffer logger and retains
-// a reference to an output logger (the logger whose input it is capturing).
-// It can optionally passthrough logs to the output logger.
+// Capture logger captures output sent to it in a buffer retaining
+// a reference to its output logger (the logger whose input it is capturing).
+// It can optionally pass logs through to the output logger.
 // Because it holds a reference to its output it can also be used to coordinate
-// Flushing of the buffer to the output logger in exceptional circumstances only
-func NewCaptureLogger(outputLogger kitlog.Logger, bufferCap channels.BufferCap,
-	passthrough bool) *CaptureLogger {
+// Flushing of the buffer to the output logger in special circumstances.
+func NewCaptureLogger(outputLogger kitlog.Logger, bufferCap channels.BufferCap, passthrough bool) *CaptureLogger {
 	return &CaptureLogger{
 		bufferLogger: NewChannelLogger(bufferCap),
 		outputLogger: outputLogger,
@@ -41,17 +40,17 @@ func (cl *CaptureLogger) Log(keyvals ...interface{}) error {
 // Sets whether the CaptureLogger is forwarding log lines sent to it through
 // to its output logger. Concurrently safe.
 func (cl *CaptureLogger) SetPassthrough(passthrough bool) {
-	cl.RWMutex.Lock()
+	cl.Lock()
 	cl.passthrough = passthrough
-	cl.RWMutex.Unlock()
+	cl.Unlock()
 }
 
 // Gets whether the CaptureLogger is forwarding log lines sent to through to its
 // OutputLogger. Concurrently Safe.
 func (cl *CaptureLogger) Passthrough() bool {
-	cl.RWMutex.RLock()
+	cl.RLock()
 	passthrough := cl.passthrough
-	cl.RWMutex.RUnlock()
+	cl.RUnlock()
 	return passthrough
 }
 
diff --git a/logging/loggers/info_trace_logger.go b/logging/loggers/info_trace_logger.go
deleted file mode 100644
index df51014787d13d90075847869a52f0a01b7d9955..0000000000000000000000000000000000000000
--- a/logging/loggers/info_trace_logger.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2017 Monax Industries Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package loggers
-
-import (
-	"github.com/eapache/channels"
-	kitlog "github.com/go-kit/kit/log"
-	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/logging/types"
-)
-
-type infoTraceLogger struct {
-	infoContext        kitlog.Logger
-	traceContext       kitlog.Logger
-	outputLogger       *kitlog.SwapLogger
-	outputLoggerErrors channels.Channel
-}
-
-// Interface assertions
-var _ types.InfoTraceLogger = (*infoTraceLogger)(nil)
-var _ kitlog.Logger = (types.InfoTraceLogger)(nil)
-
-// Create an InfoTraceLogger by passing the initial outputLogger.
-func NewInfoTraceLogger(outputLogger kitlog.Logger) (types.InfoTraceLogger, channels.Channel) {
-	// We will never halt the progress of a log emitter. If log output takes too
-	// long will start dropping log lines by using a ring buffer.
-	swapLogger := new(kitlog.SwapLogger)
-	swapLogger.Swap(outputLogger)
-	wrappedOutputLogger, errCh := wrapOutputLogger(swapLogger)
-	return &infoTraceLogger{
-		outputLogger:       swapLogger,
-		outputLoggerErrors: errCh,
-		// logging contexts
-		infoContext: kitlog.With(wrappedOutputLogger,
-			structure.ChannelKey, types.InfoChannelName,
-		),
-		traceContext: kitlog.With(wrappedOutputLogger,
-			structure.ChannelKey, types.TraceChannelName,
-		),
-	}, errCh
-}
-
-func NewNoopInfoTraceLogger() types.InfoTraceLogger {
-	logger, _ := NewInfoTraceLogger(nil)
-	return logger
-}
-
-func (l *infoTraceLogger) With(keyvals ...interface{}) types.InfoTraceLogger {
-	return &infoTraceLogger{
-		outputLogger: l.outputLogger,
-		infoContext:  kitlog.With(l.infoContext, keyvals...),
-		traceContext: kitlog.With(l.traceContext, keyvals...),
-	}
-}
-
-func (l *infoTraceLogger) WithPrefix(keyvals ...interface{}) types.InfoTraceLogger {
-	return &infoTraceLogger{
-		outputLogger: l.outputLogger,
-		infoContext:  kitlog.WithPrefix(l.infoContext, keyvals...),
-		traceContext: kitlog.WithPrefix(l.traceContext, keyvals...),
-	}
-}
-
-func (l *infoTraceLogger) Info(keyvals ...interface{}) error {
-	return l.infoContext.Log(keyvals...)
-}
-
-func (l *infoTraceLogger) Trace(keyvals ...interface{}) error {
-	return l.traceContext.Log(keyvals...)
-}
-
-func (l *infoTraceLogger) SwapOutput(infoLogger kitlog.Logger) {
-	l.outputLogger.Swap(infoLogger)
-}
-
-// If logged to as a plain kitlog logger presume the message is for Trace
-// This favours keeping Info reasonably quiet. Note that an InfoTraceLogger
-// aware adapter can make its own choices, but we tend to think of logs from
-// dependencies as less interesting than logs generated by us or specifically
-// routed by us.
-func (l *infoTraceLogger) Log(keyvals ...interface{}) error {
-	return l.Trace(keyvals...)
-}
-
-// Wrap the output loggers with a a set of standard transforms, a non-blocking
-// ChannelLogger and an outer context
-func wrapOutputLogger(outputLogger kitlog.Logger) (kitlog.Logger, channels.Channel) {
-	//return outputLogger, channels.NewDeadChannel()
-	return VectorValuedLogger(SortLogger(BurrowFormatLogger(outputLogger),
-		structure.ChannelKey, structure.MessageKey, structure.TimeKey, structure.ComponentKey)), channels.NewDeadChannel()
-}
diff --git a/logging/loggers/output_loggers.go b/logging/loggers/output_loggers.go
index c39d3873cfaf21d424e1bba17509f21e43c253eb..d22f77f8bfc446a4f79ff78466738ab9e88c472f 100644
--- a/logging/loggers/output_loggers.go
+++ b/logging/loggers/output_loggers.go
@@ -8,9 +8,7 @@ import (
 
 	kitlog "github.com/go-kit/kit/log"
 	"github.com/go-kit/kit/log/term"
-	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/logging/types"
 )
 
 const (
@@ -37,7 +35,7 @@ func NewStreamLogger(writer io.Writer, format string) (kitlog.Logger, error) {
 	case TerminalFormat:
 		logger = term.NewLogger(writer, kitlog.NewLogfmtLogger, func(keyvals ...interface{}) term.FgBgColor {
 			switch structure.Value(keyvals, structure.ChannelKey) {
-			case types.TraceChannelName:
+			case structure.TraceChannelName:
 				return term.FgBgColor{Fg: term.DarkGreen}
 			default:
 				return term.FgBgColor{Fg: term.Yellow}
@@ -52,7 +50,7 @@ func NewStreamLogger(writer io.Writer, format string) (kitlog.Logger, error) {
 	}
 	// Don't log signals
 	return kitlog.LoggerFunc(func(keyvals ...interface{}) error {
-		if logging.Signal(keyvals) != "" {
+		if structure.Signal(keyvals) != "" {
 			return nil
 		}
 		return logger.Log(keyvals...)
@@ -69,7 +67,7 @@ func NewFileLogger(path string, formatName string) (kitlog.Logger, error) {
 		return nil, err
 	}
 	return kitlog.LoggerFunc(func(keyvals ...interface{}) error {
-		if logging.Signal(keyvals) == structure.SyncSignal {
+		if structure.Signal(keyvals) == structure.SyncSignal {
 			return f.Sync()
 		}
 		return streamLogger.Log(keyvals...)
diff --git a/logging/loggers/output_loggers_test.go b/logging/loggers/output_loggers_test.go
index 77e948fc07c0f765fa6b3d8210de3a71c49943ac..6e3d83817f923a24fb698cb226aa5fc7d8e81ac3 100644
--- a/logging/loggers/output_loggers_test.go
+++ b/logging/loggers/output_loggers_test.go
@@ -5,7 +5,7 @@ import (
 	"io/ioutil"
 	"testing"
 
-	"github.com/hyperledger/burrow/logging"
+	"github.com/hyperledger/burrow/logging/structure"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -21,7 +21,7 @@ func TestNewFileLogger(t *testing.T) {
 	err = fileLogger.Log("foo", "bar")
 	require.NoError(t, err)
 
-	err = logging.Sync(fileLogger)
+	err = structure.Sync(fileLogger)
 	require.NoError(t, err)
 
 	bs, err := ioutil.ReadFile(logPath)
@@ -37,7 +37,7 @@ func TestNewStreamLogger(t *testing.T) {
 	err = logger.Log("oh", "my")
 	require.NoError(t, err)
 
-	err = logging.Sync(logger)
+	err = structure.Sync(logger)
 	require.NoError(t, err)
 
 	assert.Equal(t, "oh=my\n", string(buf.Bytes()))
diff --git a/logging/metadata.go b/logging/metadata.go
index 1699fb1a2c08e43997673ecf6789d7bc1a501262..485c8f2be568d20c70c0d9041c44d035401d4ce2 100644
--- a/logging/metadata.go
+++ b/logging/metadata.go
@@ -15,12 +15,9 @@
 package logging
 
 import (
-	"time"
-
 	kitlog "github.com/go-kit/kit/log"
 	"github.com/go-stack/stack"
 	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/logging/types"
 )
 
 const (
@@ -32,15 +29,12 @@ const (
 	infoTraceLoggerCallDepth = 5
 )
 
-var defaultTimestampUTCValuer kitlog.Valuer = func() interface{} {
-	return time.Now()
-}
-
-func WithMetadata(infoTraceLogger types.InfoTraceLogger) types.InfoTraceLogger {
-	return infoTraceLogger.With(structure.TimeKey, defaultTimestampUTCValuer,
-		structure.TraceKey, TraceValuer())
+func WithMetadata(logger *Logger) *Logger {
+	return logger.With(structure.TimeKey, kitlog.DefaultTimestampUTC,
+		structure.TraceKey, TraceValuer(),
+		structure.CallerKey, kitlog.Caller(infoTraceLoggerCallDepth))
 }
 
 func TraceValuer() kitlog.Valuer {
-	return func() interface{} { return stack.Trace().TrimBelow(stack.Caller(infoTraceLoggerCallDepth - 1)) }
+	return func() interface{} { return stack.Trace() }
 }
diff --git a/logging/structure/structure.go b/logging/structure/structure.go
index 97cfd7d3b11925ee940f6518e0e6ad7e34bf7777..41fc03128b496f5ef24d535bb0a1e1939ff86c9d 100644
--- a/logging/structure/structure.go
+++ b/logging/structure/structure.go
@@ -17,6 +17,8 @@ package structure
 import (
 	"encoding/json"
 	"fmt"
+
+	kitlog "github.com/go-kit/kit/log"
 )
 
 const (
@@ -46,7 +48,9 @@ const (
 	// Provides special instructions (that may be ignored) to downstream loggers
 	SignalKey = "__signal__"
 	// The sync signal instructs sync-able loggers to sync
-	SyncSignal = "__sync__"
+	SyncSignal       = "__sync__"
+	InfoChannelName  = "Info"
+	TraceChannelName = "Trace"
 )
 
 // Pull the specified values from a structured log line into a map.
@@ -247,3 +251,22 @@ func StringifyKey(key interface{}) string {
 		}
 	}
 }
+
+// Sends the sync signal which causes any syncing loggers to sync.
+// loggers receiving the signal should drop the signal logline from output
+func Sync(logger kitlog.Logger) error {
+	return logger.Log(SignalKey, SyncSignal)
+}
+
+// Tried to interpret the logline as a signal by matching the last key-value pair as a signal, returns empty string if
+// no match
+func Signal(keyvals []interface{}) string {
+	last := len(keyvals) - 1
+	if last > 0 && keyvals[last-1] == SignalKey {
+		signal, ok := keyvals[last].(string)
+		if ok {
+			return signal
+		}
+	}
+	return ""
+}
diff --git a/logging/types/info_trace_logger.go b/logging/types/info_trace_logger.go
deleted file mode 100644
index 613cf07ca00f6bc307998dcddee092938280e40f..0000000000000000000000000000000000000000
--- a/logging/types/info_trace_logger.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package types
-
-import kitlog "github.com/go-kit/kit/log"
-
-const (
-	InfoChannelName  = "Info"
-	TraceChannelName = "Trace"
-
-	InfoLevelName  = InfoChannelName
-	TraceLevelName = TraceChannelName
-)
-
-// InfoTraceLogger maintains provides two logging 'channels' that are interlaced
-// to provide a coarse grained filter to distinguish human-consumable 'Info'
-// messages and execution level 'Trace' messages.
-type InfoTraceLogger interface {
-	// Send a log message to the default channel of the implementation
-	kitlog.Logger
-
-	// Send an log message to the Info channel, formed of a sequence of key value
-	// pairs. Info messages should be operationally interesting to a human who is
-	// monitoring the logs. But not necessarily a human who is trying to
-	// understand or debug the system. Any handled errors or warnings should be
-	// sent to the Info channel (where you may wish to tag them with a suitable
-	// key-value pair to categorise them as such).
-	Info(keyvals ...interface{}) error
-
-	// Send an log message to the Trace channel, formed of a sequence of key-value
-	// pairs. Trace messages can be used for any state change in the system that
-	// may be of interest to a machine consumer or a human who is trying to debug
-	// the system or trying to understand the system in detail. If the messages
-	// are very point-like and contain little structure, consider using a metric
-	// instead.
-	Trace(keyvals ...interface{}) error
-
-	// A logging context (see go-kit log's Context). Takes a sequence key values
-	// via With or WithPrefix and ensures future calls to log will have those
-	// contextual values appended to the call to an underlying logger.
-	// Values can be dynamic by passing an instance of the kitlog.Valuer interface
-	// This provides an interface version of the kitlog.Context struct to be used
-	// For implementations that wrap a kitlog.Context. In addition it makes no
-	// assumption about the name or signature of the logging method(s).
-	// See InfoTraceLogger
-
-	// Establish a context by appending contextual key-values to any existing
-	// contextual values
-	With(keyvals ...interface{}) InfoTraceLogger
-
-	// Establish a context by prepending contextual key-values to any existing
-	// contextual values
-	WithPrefix(keyvals ...interface{}) InfoTraceLogger
-
-	// Hot swap the underlying outputLogger with another one to re-route messages
-	SwapOutput(outputLogger kitlog.Logger)
-}
-
-// Interface assertions
-var _ kitlog.Logger = (InfoTraceLogger)(nil)
diff --git a/permission/constants.go b/permission/constants.go
deleted file mode 100644
index c795fda0f50cd608b65e3a3b22d7ba0975cebd80..0000000000000000000000000000000000000000
--- a/permission/constants.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package permission
-
-import (
-	"github.com/hyperledger/burrow/account"
-	"github.com/hyperledger/burrow/binary"
-)
-
-var (
-	GlobalPermissionsAddress = account.Address(binary.Zero160)
-)
diff --git a/permission/permissions.go b/permission/permissions.go
index a314ae4c0f48b0e2afef277a8947fceff2a58635..5bfcf61c9205c1a6ae222e8110298759c8cd8a9a 100644
--- a/permission/permissions.go
+++ b/permission/permissions.go
@@ -18,7 +18,6 @@ import (
 	"fmt"
 	"strings"
 
-	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/permission/types"
 )
 
@@ -195,21 +194,3 @@ func PermStringToFlag(perm string) (types.PermFlag, error) {
 		return 0, fmt.Errorf("unknown permission %s", perm)
 	}
 }
-
-func GlobalPermissionsAccount(state acm.Getter) acm.Account {
-	acc, err := state.GetAccount(GlobalPermissionsAddress)
-	if err != nil {
-		panic("Could not get global permission account, but this must exist")
-	}
-	return acc
-}
-
-// Get global permissions from the account at GlobalPermissionsAddress
-func GlobalAccountPermissions(state acm.Getter) types.AccountPermissions {
-	if state == nil {
-		return types.AccountPermissions{
-			Roles: []string{},
-		}
-	}
-	return GlobalPermissionsAccount(state).Permissions()
-}
diff --git a/permission/snatives.go b/permission/snatives/snatives.go
similarity index 72%
rename from permission/snatives.go
rename to permission/snatives/snatives.go
index a29aeac949047c94015b8808995454dee4a35c96..2323d83b641b49ec8065b578499a663efe74303e 100644
--- a/permission/snatives.go
+++ b/permission/snatives/snatives.go
@@ -12,13 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package permission
+package snatives
 
 import (
 	"fmt"
 	"strings"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/permission"
 	"github.com/hyperledger/burrow/permission/types"
 )
 
@@ -35,12 +36,12 @@ type PermArgs struct {
 
 func (pa PermArgs) String() string {
 	body := make([]string, 0, 5)
-	body = append(body, fmt.Sprintf("PermFlag: %s", PermissionsString(pa.PermFlag)))
+	body = append(body, fmt.Sprintf("PermFlag: %s", permission.String(pa.PermFlag)))
 	if pa.Address != nil {
 		body = append(body, fmt.Sprintf("Address: %s", *pa.Address))
 	}
 	if pa.Permission != nil {
-		body = append(body, fmt.Sprintf("Permission: %s", PermissionsString(*pa.Permission)))
+		body = append(body, fmt.Sprintf("Permission: %s", permission.String(*pa.Permission)))
 	}
 	if pa.Role != nil {
 		body = append(body, fmt.Sprintf("Role: %s", *pa.Role))
@@ -54,10 +55,10 @@ func (pa PermArgs) String() string {
 func (pa PermArgs) EnsureValid() error {
 	pf := pa.PermFlag
 	// Address
-	if pa.Address == nil && pf != SetGlobal {
+	if pa.Address == nil && pf != permission.SetGlobal {
 		return fmt.Errorf("PermArgs for PermFlag %v requires Address to be provided but was nil", pf)
 	}
-	if pf == HasRole || pf == AddRole || pf == RemoveRole {
+	if pf == permission.HasRole || pf == permission.AddRole || pf == permission.RemoveRole {
 		// Role
 		if pa.Role == nil {
 			return fmt.Errorf("PermArgs for PermFlag %v requires Role to be provided but was nil", pf)
@@ -66,48 +67,48 @@ func (pa PermArgs) EnsureValid() error {
 	} else if pa.Permission == nil {
 		return fmt.Errorf("PermArgs for PermFlag %v requires Permission to be provided but was nil", pf)
 		// Value
-	} else if (pf == SetBase || pf == SetGlobal) && pa.Value == nil {
+	} else if (pf == permission.SetBase || pf == permission.SetGlobal) && pa.Value == nil {
 		return fmt.Errorf("PermArgs for PermFlag %v requires Value to be provided but was nil", pf)
 	}
 	return nil
 }
 
-func HasBaseArgs(address acm.Address, permission types.PermFlag) PermArgs {
+func HasBaseArgs(address acm.Address, permFlag types.PermFlag) PermArgs {
 	return PermArgs{
-		PermFlag:   HasBase,
+		PermFlag:   permission.HasBase,
 		Address:    &address,
-		Permission: &permission,
+		Permission: &permFlag,
 	}
 }
 
-func SetBaseArgs(address acm.Address, permission types.PermFlag, value bool) PermArgs {
+func SetBaseArgs(address acm.Address, permFlag types.PermFlag, value bool) PermArgs {
 	return PermArgs{
-		PermFlag:   SetBase,
+		PermFlag:   permission.SetBase,
 		Address:    &address,
-		Permission: &permission,
+		Permission: &permFlag,
 		Value:      &value,
 	}
 }
 
-func UnsetBaseArgs(address acm.Address, permission types.PermFlag) PermArgs {
+func UnsetBaseArgs(address acm.Address, permFlag types.PermFlag) PermArgs {
 	return PermArgs{
-		PermFlag:   UnsetBase,
+		PermFlag:   permission.UnsetBase,
 		Address:    &address,
-		Permission: &permission,
+		Permission: &permFlag,
 	}
 }
 
-func SetGlobalArgs(permission types.PermFlag, value bool) PermArgs {
+func SetGlobalArgs(permFlag types.PermFlag, value bool) PermArgs {
 	return PermArgs{
-		PermFlag:   SetGlobal,
-		Permission: &permission,
+		PermFlag:   permission.SetGlobal,
+		Permission: &permFlag,
 		Value:      &value,
 	}
 }
 
 func HasRoleArgs(address acm.Address, role string) PermArgs {
 	return PermArgs{
-		PermFlag: HasRole,
+		PermFlag: permission.HasRole,
 		Address:  &address,
 		Role:     &role,
 	}
@@ -115,7 +116,7 @@ func HasRoleArgs(address acm.Address, role string) PermArgs {
 
 func AddRoleArgs(address acm.Address, role string) PermArgs {
 	return PermArgs{
-		PermFlag: AddRole,
+		PermFlag: permission.AddRole,
 		Address:  &address,
 		Role:     &role,
 	}
@@ -123,7 +124,7 @@ func AddRoleArgs(address acm.Address, role string) PermArgs {
 
 func RemoveRoleArgs(address acm.Address, role string) PermArgs {
 	return PermArgs{
-		PermFlag: RemoveRole,
+		PermFlag: permission.RemoveRole,
 		Address:  &address,
 		Role:     &role,
 	}
diff --git a/permission/snatives_test.go b/permission/snatives/snatives_test.go
similarity index 65%
rename from permission/snatives_test.go
rename to permission/snatives/snatives_test.go
index f9126a8d14121d3839081eb91934090962df0201..76545151df366826e1f24deb5a6f100af8e48b2d 100644
--- a/permission/snatives_test.go
+++ b/permission/snatives/snatives_test.go
@@ -1,18 +1,19 @@
-package permission
+package snatives
 
 import (
 	"testing"
 
+	"github.com/hyperledger/burrow/permission"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPermArgs_String(t *testing.T) {
 	role := "foo"
 	value := true
-	permission := AddRole | RemoveRole
+	permFlag := permission.AddRole | permission.RemoveRole
 	permArgs := PermArgs{
-		PermFlag:   SetBase,
-		Permission: &permission,
+		PermFlag:   permission.SetBase,
+		Permission: &permFlag,
 		Role:       &role,
 		Value:      &value,
 	}
diff --git a/permission/util.go b/permission/util.go
index c2289e4335a0b0206d3fd792e81ec1ce5409b422..656761cd83030127313ede68c528ffe8973b00cd 100644
--- a/permission/util.go
+++ b/permission/util.go
@@ -115,7 +115,7 @@ func BasePermissionsString(basePermissions types.BasePermissions) string {
 	return strings.Join(permStrings, " | ")
 }
 
-func PermissionsString(permFlag types.PermFlag) string {
+func String(permFlag types.PermFlag) string {
 	permStrings, err := PermFlagToStringList(permFlag)
 	if err != nil {
 		return UnknownString
diff --git a/process/process.go b/process/process.go
index 960f5b7ef3579ef2e13250cade835a234c220363..b0058d280388146feeda2b251cc3c2ea2bde3e43 100644
--- a/process/process.go
+++ b/process/process.go
@@ -18,8 +18,9 @@ func (sf ShutdownFunc) Shutdown(ctx context.Context) error {
 }
 
 type Launcher struct {
-	Name   string
-	Launch func() (Process, error)
+	Name     string
+	Disabled bool
+	Launch   func() (Process, error)
 }
 
 type listenersServer struct {
diff --git a/project/history.go b/project/history.go
index 3c337c2fa8b914e8b73a8da3739fad7003e935a2..d4d1b5aeb2c14da54e11cb5489a9453c4b60e199 100644
--- a/project/history.go
+++ b/project/history.go
@@ -4,6 +4,23 @@ import (
 	"github.com/monax/relic"
 )
 
+// Can be used to set the commit hash version of the binary at build time with:
+// `go build -ldflags "-X github.com/hyperledger/burrow/project.commit=$(git rev-parse --short HEAD)" ./cmd/burrow`
+
+var commit = ""
+
+func Commit() string {
+	return commit
+}
+
+func FullVersion() string {
+	version := History.CurrentVersion().String()
+	if commit != "" {
+		return version + "+commit." + commit
+	}
+	return version
+}
+
 // The releases described by version string and changes, newest release first.
 // The current release is taken to be the first release in the slice, and its
 // version determines the single authoritative version for the next release.
@@ -11,6 +28,8 @@ import (
 // To cut a new release add a release to the front of this slice then run the
 // release tagging script: ./scripts/tag_release.sh
 var History relic.ImmutableHistory = relic.NewHistory("Hyperledger Burrow").MustDeclareReleases(
+	"0.18.1",
+	`Fixes for deployment`,
 	"0.18.0",
 	`Prerelease`,
 	"0.17.1",
diff --git a/rpc/config.go b/rpc/config.go
index 0b35c840b6be1d3f7191272f9cab469126c769cd..89936dec7e18fd410ef853d82da6226a2e24b174 100644
--- a/rpc/config.go
+++ b/rpc/config.go
@@ -3,22 +3,31 @@ package rpc
 import "github.com/hyperledger/burrow/rpc/v0/server"
 
 type RPCConfig struct {
-	V0 *V0Config `json:",omitempty" toml:",omitempty"`
-	TM *TMConfig `json:",omitempty" toml:",omitempty"`
+	V0       *V0Config       `json:",omitempty" toml:",omitempty"`
+	TM       *TMConfig       `json:",omitempty" toml:",omitempty"`
+	Profiler *ProfilerConfig `json:",omitempty" toml:",omitempty"`
 }
 
 type TMConfig struct {
+	Disabled      bool
 	ListenAddress string
 }
 
 type V0Config struct {
-	Server *server.ServerConfig
+	Disabled bool
+	Server   *server.ServerConfig
+}
+
+type ProfilerConfig struct {
+	Disabled      bool
+	ListenAddress string
 }
 
 func DefaultRPCConfig() *RPCConfig {
 	return &RPCConfig{
-		TM: DefaultTMConfig(),
-		V0: DefaultV0Config(),
+		TM:       DefaultTMConfig(),
+		V0:       DefaultV0Config(),
+		Profiler: DefaultProfilerConfig(),
 	}
 }
 func DefaultV0Config() *V0Config {
@@ -32,3 +41,10 @@ func DefaultTMConfig() *TMConfig {
 		ListenAddress: ":46657",
 	}
 }
+
+func DefaultProfilerConfig() *ProfilerConfig {
+	return &ProfilerConfig{
+		Disabled:      true,
+		ListenAddress: ":6060",
+	}
+}
diff --git a/rpc/result.go b/rpc/result.go
index b43d3749f198e0fed2335efaa309c9b3e50d6fce..2e51a2e65f7c205d1b505f771a430d2d54556576 100644
--- a/rpc/result.go
+++ b/rpc/result.go
@@ -135,6 +135,21 @@ type ResultGetAccount struct {
 	Account *acm.ConcreteAccount
 }
 
+type AccountHumanReadable struct {
+	Address     acm.Address
+	PublicKey   acm.PublicKey
+	Sequence    uint64
+	Balance     uint64
+	Code        []string
+	StorageRoot string
+	Permissions []string
+	Roles       []string
+}
+
+type ResultGetAccountHumanReadable struct {
+	Account *AccountHumanReadable
+}
+
 type ResultBroadcastTx struct {
 	txs.Receipt
 }
diff --git a/rpc/service.go b/rpc/service.go
index c91e7645ce90ec09fad5236c4267f5b977a14a04..13d698346c30f135f78793536539b3263cff6eb9 100644
--- a/rpc/service.go
+++ b/rpc/service.go
@@ -19,6 +19,7 @@ import (
 	"fmt"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	"github.com/hyperledger/burrow/binary"
 	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/consensus/tendermint/query"
@@ -26,73 +27,36 @@ import (
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/permission"
 	"github.com/hyperledger/burrow/project"
 	"github.com/hyperledger/burrow/txs"
 	tm_types "github.com/tendermint/tendermint/types"
+	"github.com/tmthrgd/go-hex"
 )
 
 // Magic! Should probably be configurable, but not shouldn't be so huge we
 // end up DoSing ourselves.
 const MaxBlockLookback = 100
 
-type SubscribableService interface {
-	// Events
-	Subscribe(ctx context.Context, subscriptionID string, eventID string, callback func(*ResultEvent) bool) error
-	Unsubscribe(ctx context.Context, subscriptionID string) error
-}
-
 // Base service that provides implementation for all underlying RPC methods
-type Service interface {
-	SubscribableService
-	// Transact
-	Transactor() execution.Transactor
-	// List mempool transactions pass -1 for all unconfirmed transactions
-	ListUnconfirmedTxs(maxTxs int) (*ResultListUnconfirmedTxs, error)
-	// Status
-	Status() (*ResultStatus, error)
-	NetInfo() (*ResultNetInfo, error)
-	// Accounts
-	GetAccount(address acm.Address) (*ResultGetAccount, error)
-	ListAccounts(predicate func(acm.Account) bool) (*ResultListAccounts, error)
-	GetStorage(address acm.Address, key []byte) (*ResultGetStorage, error)
-	DumpStorage(address acm.Address) (*ResultDumpStorage, error)
-	// Blockchain
-	Genesis() (*ResultGenesis, error)
-	ChainId() (*ResultChainId, error)
-	GetBlock(height uint64) (*ResultGetBlock, error)
-	ListBlocks(minHeight, maxHeight uint64) (*ResultListBlocks, error)
-	// Consensus
-	ListValidators() (*ResultListValidators, error)
-	DumpConsensusState() (*ResultDumpConsensusState, error)
-	Peers() (*ResultPeers, error)
-	// Names
-	GetName(name string) (*ResultGetName, error)
-	ListNames(predicate func(*execution.NameRegEntry) bool) (*ResultListNames, error)
-	// Private keys and signing
-	GeneratePrivateAccount() (*ResultGeneratePrivateAccount, error)
-}
-
-type service struct {
+type Service struct {
 	ctx          context.Context
-	state        acm.StateIterable
+	iterable     state.Iterable
 	subscribable event.Subscribable
 	nameReg      execution.NameRegIterable
 	blockchain   bcm.Blockchain
 	transactor   execution.Transactor
 	nodeView     query.NodeView
-	logger       logging_types.InfoTraceLogger
+	logger       *logging.Logger
 }
 
-var _ Service = &service{}
-
-func NewService(ctx context.Context, state acm.StateIterable, nameReg execution.NameRegIterable,
+func NewService(ctx context.Context, iterable state.Iterable, nameReg execution.NameRegIterable,
 	subscribable event.Subscribable, blockchain bcm.Blockchain, transactor execution.Transactor,
-	nodeView query.NodeView, logger logging_types.InfoTraceLogger) *service {
+	nodeView query.NodeView, logger *logging.Logger) *Service {
 
-	return &service{
+	return &Service{
 		ctx:          ctx,
-		state:        state,
+		iterable:     iterable,
 		nameReg:      nameReg,
 		subscribable: subscribable,
 		blockchain:   blockchain,
@@ -103,8 +67,8 @@ func NewService(ctx context.Context, state acm.StateIterable, nameReg execution.
 }
 
 // Provides a sub-service with only the subscriptions methods
-func NewSubscribableService(subscribable event.Subscribable, logger logging_types.InfoTraceLogger) *service {
-	return &service{
+func NewSubscribableService(subscribable event.Subscribable, logger *logging.Logger) *Service {
+	return &Service{
 		ctx:          context.Background(),
 		subscribable: subscribable,
 		logger:       logger.With(structure.ComponentKey, "Service"),
@@ -113,11 +77,11 @@ func NewSubscribableService(subscribable event.Subscribable, logger logging_type
 
 // Transacting...
 
-func (s *service) Transactor() execution.Transactor {
+func (s *Service) Transactor() execution.Transactor {
 	return s.transactor
 }
 
-func (s *service) ListUnconfirmedTxs(maxTxs int) (*ResultListUnconfirmedTxs, error) {
+func (s *Service) ListUnconfirmedTxs(maxTxs int) (*ResultListUnconfirmedTxs, error) {
 	// Get all transactions for now
 	transactions, err := s.nodeView.MempoolTransactions(maxTxs)
 	if err != nil {
@@ -133,11 +97,11 @@ func (s *service) ListUnconfirmedTxs(maxTxs int) (*ResultListUnconfirmedTxs, err
 	}, nil
 }
 
-func (s *service) Subscribe(ctx context.Context, subscriptionID string, eventID string,
+func (s *Service) Subscribe(ctx context.Context, subscriptionID string, eventID string,
 	callback func(resultEvent *ResultEvent) bool) error {
 
 	queryBuilder := event.QueryForEventID(eventID)
-	logging.InfoMsg(s.logger, "Subscribing to events",
+	s.logger.InfoMsg("Subscribing to events",
 		"query", queryBuilder.String(),
 		"subscription_id", subscriptionID,
 		"event_id", eventID)
@@ -145,7 +109,7 @@ func (s *service) Subscribe(ctx context.Context, subscriptionID string, eventID
 		func(message interface{}) bool {
 			resultEvent, err := NewResultEvent(eventID, message)
 			if err != nil {
-				logging.InfoMsg(s.logger, "Received event that could not be mapped to ResultEvent",
+				s.logger.InfoMsg("Received event that could not be mapped to ResultEvent",
 					structure.ErrorKey, err,
 					"subscription_id", subscriptionID,
 					"event_id", eventID)
@@ -155,8 +119,8 @@ func (s *service) Subscribe(ctx context.Context, subscriptionID string, eventID
 		})
 }
 
-func (s *service) Unsubscribe(ctx context.Context, subscriptionID string) error {
-	logging.InfoMsg(s.logger, "Unsubscribing from events",
+func (s *Service) Unsubscribe(ctx context.Context, subscriptionID string) error {
+	s.logger.InfoMsg("Unsubscribing from events",
 		"subscription_id", subscriptionID)
 	err := s.subscribable.UnsubscribeAll(ctx, subscriptionID)
 	if err != nil {
@@ -165,7 +129,7 @@ func (s *service) Unsubscribe(ctx context.Context, subscriptionID string) error
 	return nil
 }
 
-func (s *service) Status() (*ResultStatus, error) {
+func (s *Service) Status() (*ResultStatus, error) {
 	tip := s.blockchain.Tip()
 	latestHeight := tip.LastBlockHeight()
 	var (
@@ -193,7 +157,7 @@ func (s *service) Status() (*ResultStatus, error) {
 	}, nil
 }
 
-func (s *service) ChainId() (*ResultChainId, error) {
+func (s *Service) ChainId() (*ResultChainId, error) {
 	return &ResultChainId{
 		ChainName:   s.blockchain.GenesisDoc().ChainName,
 		ChainId:     s.blockchain.ChainID(),
@@ -201,7 +165,7 @@ func (s *service) ChainId() (*ResultChainId, error) {
 	}, nil
 }
 
-func (s *service) Peers() (*ResultPeers, error) {
+func (s *Service) Peers() (*ResultPeers, error) {
 	peers := make([]*Peer, s.nodeView.Peers().Size())
 	for i, peer := range s.nodeView.Peers().List() {
 		peers[i] = &Peer{
@@ -214,7 +178,7 @@ func (s *service) Peers() (*ResultPeers, error) {
 	}, nil
 }
 
-func (s *service) NetInfo() (*ResultNetInfo, error) {
+func (s *Service) NetInfo() (*ResultNetInfo, error) {
 	listening := s.nodeView.IsListening()
 	listeners := []string{}
 	for _, listener := range s.nodeView.Listeners() {
@@ -231,27 +195,27 @@ func (s *service) NetInfo() (*ResultNetInfo, error) {
 	}, nil
 }
 
-func (s *service) Genesis() (*ResultGenesis, error) {
+func (s *Service) Genesis() (*ResultGenesis, error) {
 	return &ResultGenesis{
 		Genesis: s.blockchain.GenesisDoc(),
 	}, nil
 }
 
 // Accounts
-func (s *service) GetAccount(address acm.Address) (*ResultGetAccount, error) {
-	acc, err := s.state.GetAccount(address)
+func (s *Service) GetAccount(address acm.Address) (*ResultGetAccount, error) {
+	acc, err := s.iterable.GetAccount(address)
 	if err != nil {
 		return nil, err
 	}
-	s.logger.Trace("method", "GetAccount",
+	s.logger.Trace.Log("method", "GetAccount",
 		"address", address,
 		"sequence", acc.Sequence())
 	return &ResultGetAccount{Account: acm.AsConcreteAccount(acc)}, nil
 }
 
-func (s *service) ListAccounts(predicate func(acm.Account) bool) (*ResultListAccounts, error) {
+func (s *Service) ListAccounts(predicate func(acm.Account) bool) (*ResultListAccounts, error) {
 	accounts := make([]*acm.ConcreteAccount, 0)
-	s.state.IterateAccounts(func(account acm.Account) (stop bool) {
+	s.iterable.IterateAccounts(func(account acm.Account) (stop bool) {
 		if predicate(account) {
 			accounts = append(accounts, acm.AsConcreteAccount(account))
 		}
@@ -264,8 +228,8 @@ func (s *service) ListAccounts(predicate func(acm.Account) bool) (*ResultListAcc
 	}, nil
 }
 
-func (s *service) GetStorage(address acm.Address, key []byte) (*ResultGetStorage, error) {
-	account, err := s.state.GetAccount(address)
+func (s *Service) GetStorage(address acm.Address, key []byte) (*ResultGetStorage, error) {
+	account, err := s.iterable.GetAccount(address)
 	if err != nil {
 		return nil, err
 	}
@@ -273,7 +237,7 @@ func (s *service) GetStorage(address acm.Address, key []byte) (*ResultGetStorage
 		return nil, fmt.Errorf("UnknownAddress: %s", address)
 	}
 
-	value, err := s.state.GetStorage(address, binary.LeftPadWord256(key))
+	value, err := s.iterable.GetStorage(address, binary.LeftPadWord256(key))
 	if err != nil {
 		return nil, err
 	}
@@ -283,8 +247,8 @@ func (s *service) GetStorage(address acm.Address, key []byte) (*ResultGetStorage
 	return &ResultGetStorage{Key: key, Value: value.UnpadLeft()}, nil
 }
 
-func (s *service) DumpStorage(address acm.Address) (*ResultDumpStorage, error) {
-	account, err := s.state.GetAccount(address)
+func (s *Service) DumpStorage(address acm.Address) (*ResultDumpStorage, error) {
+	account, err := s.iterable.GetAccount(address)
 	if err != nil {
 		return nil, err
 	}
@@ -292,7 +256,7 @@ func (s *service) DumpStorage(address acm.Address) (*ResultDumpStorage, error) {
 		return nil, fmt.Errorf("UnknownAddress: %X", address)
 	}
 	var storageItems []StorageItem
-	s.state.IterateStorage(address, func(key, value binary.Word256) (stop bool) {
+	s.iterable.IterateStorage(address, func(key, value binary.Word256) (stop bool) {
 		storageItems = append(storageItems, StorageItem{Key: key.UnpadLeft(), Value: value.UnpadLeft()})
 		return
 	})
@@ -302,8 +266,38 @@ func (s *service) DumpStorage(address acm.Address) (*ResultDumpStorage, error) {
 	}, nil
 }
 
+func (s *Service) GetAccountHumanReadable(address acm.Address) (*ResultGetAccountHumanReadable, error) {
+	acc, err := s.iterable.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return &ResultGetAccountHumanReadable{}, nil
+	}
+	tokens, err := acc.Code().Tokens()
+	if acc == nil {
+		return &ResultGetAccountHumanReadable{}, nil
+	}
+	perms, err := permission.BasePermissionsToStringList(acc.Permissions().Base)
+	if acc == nil {
+		return &ResultGetAccountHumanReadable{}, nil
+	}
+	return &ResultGetAccountHumanReadable{
+		Account: &AccountHumanReadable{
+			Address:     acc.Address(),
+			PublicKey:   acc.PublicKey(),
+			Sequence:    acc.Sequence(),
+			Balance:     acc.Balance(),
+			Code:        tokens,
+			StorageRoot: hex.EncodeUpperToString(acc.StorageRoot()),
+			Permissions: perms,
+			Roles:       acc.Permissions().Roles,
+		},
+	}, nil
+}
+
 // Name registry
-func (s *service) GetName(name string) (*ResultGetName, error) {
+func (s *Service) GetName(name string) (*ResultGetName, error) {
 	entry, err := s.nameReg.GetNameRegEntry(name)
 	if err != nil {
 		return nil, err
@@ -314,7 +308,7 @@ func (s *service) GetName(name string) (*ResultGetName, error) {
 	return &ResultGetName{Entry: entry}, nil
 }
 
-func (s *service) ListNames(predicate func(*execution.NameRegEntry) bool) (*ResultListNames, error) {
+func (s *Service) ListNames(predicate func(*execution.NameRegEntry) bool) (*ResultListNames, error) {
 	var names []*execution.NameRegEntry
 	s.nameReg.IterateNameRegEntries(func(entry *execution.NameRegEntry) (stop bool) {
 		if predicate(entry) {
@@ -328,7 +322,7 @@ func (s *service) ListNames(predicate func(*execution.NameRegEntry) bool) (*Resu
 	}, nil
 }
 
-func (s *service) GetBlock(height uint64) (*ResultGetBlock, error) {
+func (s *Service) GetBlock(height uint64) (*ResultGetBlock, error) {
 	return &ResultGetBlock{
 		Block:     s.nodeView.BlockStore().LoadBlock(int64(height)),
 		BlockMeta: s.nodeView.BlockStore().LoadBlockMeta(int64(height)),
@@ -340,7 +334,7 @@ func (s *service) GetBlock(height uint64) (*ResultGetBlock, error) {
 // from the top of the range of blocks.
 // Passing 0 for maxHeight sets the upper height of the range to the current
 // blockchain height.
-func (s *service) ListBlocks(minHeight, maxHeight uint64) (*ResultListBlocks, error) {
+func (s *Service) ListBlocks(minHeight, maxHeight uint64) (*ResultListBlocks, error) {
 	latestHeight := s.blockchain.Tip().LastBlockHeight()
 
 	if minHeight == 0 {
@@ -365,7 +359,7 @@ func (s *service) ListBlocks(minHeight, maxHeight uint64) (*ResultListBlocks, er
 	}, nil
 }
 
-func (s *service) ListValidators() (*ResultListValidators, error) {
+func (s *Service) ListValidators() (*ResultListValidators, error) {
 	// TODO: when we reintroduce support for bonding and unbonding update this
 	// to reflect the mutable bonding state
 	validators := s.blockchain.Validators()
@@ -380,7 +374,7 @@ func (s *service) ListValidators() (*ResultListValidators, error) {
 	}, nil
 }
 
-func (s *service) DumpConsensusState() (*ResultDumpConsensusState, error) {
+func (s *Service) DumpConsensusState() (*ResultDumpConsensusState, error) {
 	peerRoundState, err := s.nodeView.PeerRoundStates()
 	if err != nil {
 		return nil, err
@@ -391,7 +385,7 @@ func (s *service) DumpConsensusState() (*ResultDumpConsensusState, error) {
 	}, nil
 }
 
-func (s *service) GeneratePrivateAccount() (*ResultGeneratePrivateAccount, error) {
+func (s *Service) GeneratePrivateAccount() (*ResultGeneratePrivateAccount, error) {
 	privateAccount, err := acm.GeneratePrivateAccount()
 	if err != nil {
 		return nil, err
diff --git a/rpc/tm/integration/shared.go b/rpc/tm/integration/shared.go
index d7ad492993dc992d02412d5b61ba299fcd514d73..2849634c4418dd5e1219ca256fe8c7ac93bbc037 100644
--- a/rpc/tm/integration/shared.go
+++ b/rpc/tm/integration/shared.go
@@ -35,9 +35,9 @@ import (
 	"github.com/hyperledger/burrow/core"
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/lifecycle"
-	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/permission"
 	"github.com/hyperledger/burrow/rpc"
 	tm_client "github.com/hyperledger/burrow/rpc/tm/client"
@@ -80,7 +80,7 @@ func TestWrapper(runner func() int) int {
 	os.Chdir(testDir)
 
 	tmConf := tm_config.DefaultConfig()
-	logger := loggers.NewNoopInfoTraceLogger()
+	logger := logging.NewNoopLogger()
 	if debugLogging {
 		var err error
 		// Change config as needed
@@ -107,7 +107,8 @@ func TestWrapper(runner func() int) int {
 
 	privValidator := validator.NewPrivValidatorMemory(privateAccounts[0], privateAccounts[0])
 	genesisDoc = testGenesisDoc()
-	kernel, err := core.NewKernel(context.Background(), privValidator, genesisDoc, tmConf, rpc.DefaultRPCConfig(), logger)
+	kernel, err := core.NewKernel(context.Background(), privValidator, genesisDoc, tmConf, rpc.DefaultRPCConfig(),
+		nil, logger)
 	if err != nil {
 		panic(err)
 	}
diff --git a/rpc/tm/methods.go b/rpc/tm/methods.go
index 7da5d22b553dba8d0a91746a1b853da5522ac267..719f8cd1e4c927a6e98c6649db5b77327eff61fd 100644
--- a/rpc/tm/methods.go
+++ b/rpc/tm/methods.go
@@ -9,7 +9,6 @@ import (
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/hyperledger/burrow/txs"
 	gorpc "github.com/tendermint/tendermint/rpc/lib/server"
@@ -18,6 +17,7 @@ import (
 
 // Method names
 const (
+	BroadcastTx = "broadcast_tx"
 	Subscribe   = "subscribe"
 	Unsubscribe = "unsubscribe"
 
@@ -26,19 +26,19 @@ const (
 	NetInfo = "net_info"
 
 	// Accounts
-	ListAccounts = "list_accounts"
-	GetAccount   = "get_account"
-	GetStorage   = "get_storage"
-	DumpStorage  = "dump_storage"
+	ListAccounts    = "list_accounts"
+	GetAccount      = "get_account"
+	GetStorage      = "get_storage"
+	DumpStorage     = "dump_storage"
+	GetAccountHuman = "get_account_human"
 
 	// Simulated call
 	Call     = "call"
 	CallCode = "call_code"
 
 	// Names
-	GetName     = "get_name"
-	ListNames   = "list_names"
-	BroadcastTx = "broadcast_tx"
+	GetName   = "get_name"
+	ListNames = "list_names"
 
 	// Blockchain
 	Genesis    = "genesis"
@@ -58,8 +58,8 @@ const (
 
 const SubscriptionTimeoutSeconds = 5 * time.Second
 
-func GetRoutes(service rpc.Service, logger logging_types.InfoTraceLogger) map[string]*gorpc.RPCFunc {
-	logger = logging.WithScope(logger, "GetRoutes")
+func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.RPCFunc {
+	logger = logger.WithScope("GetRoutes")
 	return map[string]*gorpc.RPCFunc{
 		// Transact
 		BroadcastTx: gorpc.NewRPCFunc(func(tx txs.Wrapper) (*rpc.ResultBroadcastTx, error) {
@@ -107,7 +107,7 @@ func GetRoutes(service rpc.Service, logger logging_types.InfoTraceLogger) map[st
 				keepAlive := wsCtx.TryWriteRPCResponse(rpctypes.NewRPCSuccessResponse(
 					EventResponseID(wsCtx.Request.ID, eventID), resultEvent))
 				if !keepAlive {
-					logging.InfoMsg(logger, "dropping subscription because could not write to websocket",
+					logger.InfoMsg("dropping subscription because could not write to websocket",
 						"subscription_id", subscriptionID,
 						"event_id", eventID)
 				}
@@ -146,9 +146,10 @@ func GetRoutes(service rpc.Service, logger logging_types.InfoTraceLogger) map[st
 			})
 		}, ""),
 
-		GetAccount:  gorpc.NewRPCFunc(service.GetAccount, "address"),
-		GetStorage:  gorpc.NewRPCFunc(service.GetStorage, "address,key"),
-		DumpStorage: gorpc.NewRPCFunc(service.DumpStorage, "address"),
+		GetAccount:      gorpc.NewRPCFunc(service.GetAccount, "address"),
+		GetStorage:      gorpc.NewRPCFunc(service.GetStorage, "address,key"),
+		DumpStorage:     gorpc.NewRPCFunc(service.DumpStorage, "address"),
+		GetAccountHuman: gorpc.NewRPCFunc(service.GetAccountHumanReadable, "address"),
 
 		// Blockchain
 		Genesis:    gorpc.NewRPCFunc(service.Genesis, ""),
diff --git a/rpc/tm/server.go b/rpc/tm/server.go
index 25f5f5cd8baae698fa74d7ab53af6290e6d2604c..4df1e3db5a9114ace449ddd5e6ba112788513aea 100644
--- a/rpc/tm/server.go
+++ b/rpc/tm/server.go
@@ -20,14 +20,14 @@ import (
 
 	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/event"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/tendermint/tendermint/rpc/lib/server"
 )
 
-func StartServer(service rpc.Service, pattern, listenAddress string, emitter event.Emitter,
-	logger logging_types.InfoTraceLogger) (net.Listener, error) {
+func StartServer(service *rpc.Service, pattern, listenAddress string, emitter event.Emitter,
+	logger *logging.Logger) (net.Listener, error) {
 
 	logger = logger.With(structure.ComponentKey, "RPC_TM")
 	routes := GetRoutes(service, logger)
diff --git a/rpc/v0/json_service.go b/rpc/v0/json_service.go
index 50cad08a41326059d6cd6838d74ee3aab2b49eea..cac693d2a0bd5960aed26ec0cd223e5687ef858f 100644
--- a/rpc/v0/json_service.go
+++ b/rpc/v0/json_service.go
@@ -21,7 +21,6 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/hyperledger/burrow/rpc/v0/server"
 )
@@ -82,20 +81,20 @@ func (jrs *JsonRpcServer) handleFunc(c *gin.Context) {
 // Used for Burrow. Implements server.HttpService
 type JSONService struct {
 	codec           rpc.Codec
-	service         rpc.Service
+	service         *rpc.Service
 	eventSubs       *Subscriptions
 	defaultHandlers map[string]RequestHandlerFunc
-	logger          logging_types.InfoTraceLogger
+	logger          *logging.Logger
 }
 
 // Create a new JSON-RPC 2.0 service for burrow (tendermint).
-func NewJSONService(codec rpc.Codec, service rpc.Service, logger logging_types.InfoTraceLogger) server.HttpService {
+func NewJSONService(codec rpc.Codec, service *rpc.Service, logger *logging.Logger) server.HttpService {
 
 	tmhttps := &JSONService{
 		codec:     codec,
 		service:   service,
 		eventSubs: NewSubscriptions(service),
-		logger:    logging.WithScope(logger, "NewJSONService"),
+		logger:    logger.WithScope("NewJSONService"),
 	}
 
 	dhMap := GetMethods(codec, service, tmhttps.logger)
@@ -132,7 +131,7 @@ func (js *JSONService) Process(r *http.Request, w http.ResponseWriter) {
 	mName := req.Method
 
 	if handler, ok := js.defaultHandlers[mName]; ok {
-		logging.TraceMsg(js.logger, "Request received",
+		js.logger.TraceMsg("Request received",
 			"id", req.Id,
 			"method", req.Method,
 			"params", string(req.Params))
diff --git a/rpc/v0/methods.go b/rpc/v0/methods.go
index aa4416b998757c5adc72856ea0c38ba380b04080..ef994e04dc76916301f9428fdf6255948c7cf2c2 100644
--- a/rpc/v0/methods.go
+++ b/rpc/v0/methods.go
@@ -17,7 +17,7 @@ package v0
 import (
 	acm "github.com/hyperledger/burrow/account"
 	"github.com/hyperledger/burrow/execution"
-	logging_types "github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/hyperledger/burrow/rpc/filters"
 	"github.com/hyperledger/burrow/txs"
@@ -63,7 +63,7 @@ const (
 type RequestHandlerFunc func(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error)
 
 // Private. Create a method name -> method handler map.
-func GetMethods(codec rpc.Codec, service rpc.Service, logger logging_types.InfoTraceLogger) map[string]RequestHandlerFunc {
+func GetMethods(codec rpc.Codec, service *rpc.Service, logger *logging.Logger) map[string]RequestHandlerFunc {
 	accountFilterFactory := filters.NewAccountFilterFactory()
 	nameRegFilterFactory := filters.NewNameRegFilterFactory()
 
diff --git a/rpc/v0/server/server.go b/rpc/v0/server/server.go
index e79e717be00ee8aaab75fe4fd9bc4796af7c7317..9edc900f03d42fe5640e2edf8108dc1a11b2cfdc 100644
--- a/rpc/v0/server/server.go
+++ b/rpc/v0/server/server.go
@@ -24,7 +24,6 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/tommy351/gin-cors"
 	"gopkg.in/tylerb/graceful.v1"
 )
@@ -59,7 +58,7 @@ type ServeProcess struct {
 	startListenChans []chan struct{}
 	stopListenChans  []chan struct{}
 	srv              *graceful.Server
-	logger           logging_types.InfoTraceLogger
+	logger           *logging.Logger
 }
 
 // Initializes all the servers and starts listening for connections.
@@ -120,7 +119,7 @@ func (serveProcess *ServeProcess) Start() error {
 		lst = l
 	}
 	serveProcess.srv = srv
-	logging.InfoMsg(serveProcess.logger, "Server started.",
+	serveProcess.logger.InfoMsg("Server started.",
 		"chain_id", serveProcess.config.ChainId,
 		"address", serveProcess.config.Bind.Address,
 		"port", serveProcess.config.Bind.Port)
@@ -139,14 +138,14 @@ func (serveProcess *ServeProcess) Start() error {
 	// calls 'Stop' on the process.
 	go func() {
 		<-serveProcess.stopChan
-		logging.InfoMsg(serveProcess.logger, "Close signal sent to server.")
+		serveProcess.logger.InfoMsg("Close signal sent to server.")
 		serveProcess.srv.Stop(killTime)
 	}()
 	// Listen to the servers stop event. It is triggered when
 	// the server has been fully shut down.
 	go func() {
 		<-serveProcess.srv.StopChan()
-		logging.InfoMsg(serveProcess.logger, "Server stop event fired. Good bye.")
+		serveProcess.logger.InfoMsg("Server stop event fired. Good bye.")
 		for _, c := range serveProcess.stopListenChans {
 			c <- struct{}{}
 		}
@@ -198,7 +197,7 @@ func (serveProcess *ServeProcess) StopEventChannel() <-chan struct{} {
 }
 
 // Creates a new serve process.
-func NewServeProcess(config *ServerConfig, logger logging_types.InfoTraceLogger,
+func NewServeProcess(config *ServerConfig, logger *logging.Logger,
 	servers ...Server) (*ServeProcess, error) {
 	var scfg ServerConfig
 	if config == nil {
@@ -216,14 +215,14 @@ func NewServeProcess(config *ServerConfig, logger logging_types.InfoTraceLogger,
 		startListenChans: startListeners,
 		stopListenChans:  stopListeners,
 		srv:              nil,
-		logger:           logging.WithScope(logger, "ServeProcess"),
+		logger:           logger.WithScope("ServeProcess"),
 	}
 	return sp, nil
 }
 
 // Used to enable log15 logging instead of the default Gin logging.
-func logHandler(logger logging_types.InfoTraceLogger) gin.HandlerFunc {
-	logger = logging.WithScope(logger, "ginLogHandler")
+func logHandler(logger *logging.Logger) gin.HandlerFunc {
+	logger = logger.WithScope("ginLogHandler")
 	return func(c *gin.Context) {
 
 		path := c.Request.URL.Path
@@ -236,7 +235,7 @@ func logHandler(logger logging_types.InfoTraceLogger) gin.HandlerFunc {
 		statusCode := c.Writer.Status()
 		comment := c.Errors.String()
 
-		logger.Info("client_ip", clientIP,
+		logger.Info.Log("client_ip", clientIP,
 			"status_code", statusCode,
 			"method", method,
 			"path", path,
diff --git a/rpc/v0/server/websocket.go b/rpc/v0/server/websocket.go
index b54e84ea827517a3781e6f6ed7a301db4ae868fe..cda4f7def80b26957378e6d789db9a1e4e735f9c 100644
--- a/rpc/v0/server/websocket.go
+++ b/rpc/v0/server/websocket.go
@@ -24,7 +24,6 @@ import (
 	"github.com/gin-gonic/gin"
 	"github.com/gorilla/websocket"
 	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 )
 
 // TODO too much fluff. Should probably phase gorilla out and move closer
@@ -55,7 +54,7 @@ type WebSocketServer struct {
 	sessionManager *SessionManager
 	config         *ServerConfig
 	allOrigins     bool
-	logger         logging_types.InfoTraceLogger
+	logger         *logging.Logger
 }
 
 // Create a new server.
@@ -64,11 +63,11 @@ type WebSocketServer struct {
 // upgraded to websockets. Requesting a websocket connection will fail with a 503 if
 // the server is at capacity.
 func NewWebSocketServer(maxSessions uint16, service WebSocketService,
-	logger logging_types.InfoTraceLogger) *WebSocketServer {
+	logger *logging.Logger) *WebSocketServer {
 	return &WebSocketServer{
 		maxSessions:    maxSessions,
 		sessionManager: NewSessionManager(maxSessions, service, logger),
-		logger:         logging.WithScope(logger, "WebSocketServer"),
+		logger:         logger.WithScope("WebSocketServer"),
 	}
 }
 
@@ -114,7 +113,7 @@ func (wsServer *WebSocketServer) handleFunc(c *gin.Context) {
 	if uErr != nil {
 		errMsg := "Failed to upgrade to websocket connection"
 		http.Error(w, fmt.Sprintf("%s: %s", errMsg, uErr.Error()), 400)
-		logging.InfoMsg(wsServer.logger, errMsg, "error", uErr)
+		wsServer.logger.InfoMsg(errMsg, "error", uErr)
 		return
 	}
 
@@ -123,12 +122,12 @@ func (wsServer *WebSocketServer) handleFunc(c *gin.Context) {
 	if cErr != nil {
 		errMsg := "Failed to establish websocket connection"
 		http.Error(w, fmt.Sprintf("%s: %s", errMsg, cErr.Error()), 503)
-		logging.InfoMsg(wsServer.logger, errMsg, "error", cErr)
+		wsServer.logger.InfoMsg(errMsg, "error", cErr)
 		return
 	}
 
 	// Start the connection.
-	logging.InfoMsg(wsServer.logger, "New websocket connection",
+	wsServer.logger.InfoMsg("New websocket connection",
 		"session_id", session.id)
 	session.Open()
 }
@@ -152,13 +151,13 @@ type WSSession struct {
 	service        WebSocketService
 	opened         bool
 	closed         bool
-	logger         logging_types.InfoTraceLogger
+	logger         *logging.Logger
 }
 
 // Write a text message to the client.
 func (wsSession *WSSession) Write(msg []byte) error {
 	if wsSession.closed {
-		logging.InfoMsg(wsSession.logger, "Attempting to write to closed session.")
+		wsSession.logger.InfoMsg("Attempting to write to closed session.")
 		return fmt.Errorf("Session is closed")
 	}
 	wsSession.writeChan <- msg
@@ -191,7 +190,7 @@ func (wsSession *WSSession) Close() {
 		wsSession.closed = true
 		wsSession.wsConn.Close()
 		wsSession.sessionManager.removeSession(wsSession.id)
-		logging.InfoMsg(wsSession.logger, "Closing websocket connection.",
+		wsSession.logger.InfoMsg("Closing websocket connection.",
 			"remaining_active_sessions", len(wsSession.sessionManager.activeSessions))
 		wsSession.sessionManager.notifyClosed(wsSession)
 	}
@@ -240,14 +239,14 @@ func (wsSession *WSSession) readPump() {
 		// Read error.
 		if err != nil {
 			// Socket could have been gracefully closed, so not really an error.
-			logging.InfoMsg(wsSession.logger,
+			wsSession.logger.InfoMsg(
 				"Socket closed. Removing.", "error", err)
 			wsSession.writeCloseChan <- struct{}{}
 			return
 		}
 
 		if msgType != websocket.TextMessage {
-			logging.InfoMsg(wsSession.logger,
+			wsSession.logger.InfoMsg(
 				"Receiving non text-message from client, closing.")
 			wsSession.writeCloseChan <- struct{}{}
 			return
@@ -292,7 +291,7 @@ func (wsSession *WSSession) writePump() {
 			err := wsSession.wsConn.WriteMessage(websocket.TextMessage, msg)
 			if err != nil {
 				// Could be due to the socket being closed so not really an error.
-				logging.InfoMsg(wsSession.logger,
+				wsSession.logger.InfoMsg(
 					"Writing to socket failed. Closing.")
 				return
 			}
@@ -320,12 +319,12 @@ type SessionManager struct {
 	service         WebSocketService
 	openEventChans  []chan *WSSession
 	closeEventChans []chan *WSSession
-	logger          logging_types.InfoTraceLogger
+	logger          *logging.Logger
 }
 
 // Create a new WebsocketManager.
 func NewSessionManager(maxSessions uint16, wss WebSocketService,
-	logger logging_types.InfoTraceLogger) *SessionManager {
+	logger *logging.Logger) *SessionManager {
 	return &SessionManager{
 		maxSessions:     maxSessions,
 		activeSessions:  make(map[uint]*WSSession),
@@ -334,7 +333,7 @@ func NewSessionManager(maxSessions uint16, wss WebSocketService,
 		service:         wss,
 		openEventChans:  []chan *WSSession{},
 		closeEventChans: []chan *WSSession{},
-		logger:          logging.WithScope(logger, "SessionManager"),
+		logger:          logger.WithScope("SessionManager"),
 	}
 }
 
@@ -417,8 +416,7 @@ func (sessionManager *SessionManager) createSession(wsConn *websocket.Conn) (*WS
 		writeChan:      make(chan []byte, maxMessageSize),
 		writeCloseChan: make(chan struct{}),
 		service:        sessionManager.service,
-		logger: logging.WithScope(sessionManager.logger, "WSSession").
-			With("session_id", newId),
+		logger:         sessionManager.logger.WithScope("WSSession").With("session_id", newId),
 	}
 	sessionManager.activeSessions[conn.id] = conn
 	return conn, nil
diff --git a/rpc/v0/subscriptions.go b/rpc/v0/subscriptions.go
index dbfab6f76fd6ef83e48dce613e0154f0c62da146..8bb91864790cfc3d08c6d790c5da96ca0ed2a2ec 100644
--- a/rpc/v0/subscriptions.go
+++ b/rpc/v0/subscriptions.go
@@ -62,12 +62,12 @@ func (subsCache *SubscriptionsCache) poll() []interface{} {
 // Catches events that callers subscribe to and adds them to an array ready to be polled.
 type Subscriptions struct {
 	mtx     *sync.RWMutex
-	service rpc.Service
+	service *rpc.Service
 	subs    map[string]*SubscriptionsCache
 	reap    bool
 }
 
-func NewSubscriptions(service rpc.Service) *Subscriptions {
+func NewSubscriptions(service *rpc.Service) *Subscriptions {
 	es := &Subscriptions{
 		mtx:     &sync.RWMutex{},
 		service: service,
diff --git a/rpc/v0/subscriptions_test.go b/rpc/v0/subscriptions_test.go
index 45d2130a32a97804c7391a02cc5bdb2371b69de4..c3032dd6f861a394a2caa3388f51c2f89b83a7dd 100644
--- a/rpc/v0/subscriptions_test.go
+++ b/rpc/v0/subscriptions_test.go
@@ -22,7 +22,7 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/event"
-	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/stretchr/testify/assert"
 )
@@ -36,8 +36,8 @@ func TestSubReaping(t *testing.T) {
 	reaperThreshold = 200 * time.Millisecond
 	reaperTimeout = 100 * time.Millisecond
 
-	mee := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
-	eSubs := NewSubscriptions(rpc.NewSubscribableService(mee, loggers.NewNoopInfoTraceLogger()))
+	mee := event.NewEmitter(logging.NewNoopLogger())
+	eSubs := NewSubscriptions(rpc.NewSubscribableService(mee, logging.NewNoopLogger()))
 	doneChan := make(chan error)
 	go func() {
 		for i := 0; i < NUM_SUBS; i++ {
@@ -80,8 +80,8 @@ func TestSubManualClose(t *testing.T) {
 	reaperThreshold = 10000 * time.Millisecond
 	reaperTimeout = 10000 * time.Millisecond
 
-	mee := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
-	eSubs := NewSubscriptions(rpc.NewSubscribableService(mee, loggers.NewNoopInfoTraceLogger()))
+	mee := event.NewEmitter(logging.NewNoopLogger())
+	eSubs := NewSubscriptions(rpc.NewSubscribableService(mee, logging.NewNoopLogger()))
 	doneChan := make(chan error)
 	go func() {
 		for i := 0; i < NUM_SUBS; i++ {
@@ -128,8 +128,8 @@ func TestSubFlooding(t *testing.T) {
 	reaperTimeout = 10000 * time.Millisecond
 	// Crank it up. Now pressure is 10 times higher on each sub.
 	mockInterval = 1 * time.Millisecond
-	mee := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
-	eSubs := NewSubscriptions(rpc.NewSubscribableService(mee, loggers.NewNoopInfoTraceLogger()))
+	mee := event.NewEmitter(logging.NewNoopLogger())
+	eSubs := NewSubscriptions(rpc.NewSubscribableService(mee, logging.NewNoopLogger()))
 	doneChan := make(chan error)
 	go func() {
 		for i := 0; i < NUM_SUBS; i++ {
diff --git a/rpc/v0/websocket_service.go b/rpc/v0/websocket_service.go
index 17b84e4409b54ed63d4db14c0a85217f7d02283a..ed75f1ce0cd0ce3bb22373468a6dcb59fbee2519 100644
--- a/rpc/v0/websocket_service.go
+++ b/rpc/v0/websocket_service.go
@@ -22,7 +22,6 @@ import (
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	logging_types "github.com/hyperledger/burrow/logging/types"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/hyperledger/burrow/rpc/v0/server"
 )
@@ -30,17 +29,17 @@ import (
 // Used for Burrow. Implements WebSocketService.
 type WebsocketService struct {
 	codec           rpc.Codec
-	service         rpc.Service
+	service         *rpc.Service
 	defaultHandlers map[string]RequestHandlerFunc
-	logger          logging_types.InfoTraceLogger
+	logger          *logging.Logger
 }
 
 // Create a new websocket service.
-func NewWebsocketService(codec rpc.Codec, service rpc.Service, logger logging_types.InfoTraceLogger) server.WebSocketService {
+func NewWebsocketService(codec rpc.Codec, service *rpc.Service, logger *logging.Logger) server.WebSocketService {
 	tmwss := &WebsocketService{
 		codec:   codec,
 		service: service,
-		logger:  logging.WithScope(logger, "NewWebsocketService"),
+		logger:  logger.WithScope("NewWebsocketService"),
 	}
 	dhMap := GetMethods(codec, service, tmwss.logger)
 	// Events
@@ -55,7 +54,7 @@ func (ws *WebsocketService) Process(msg []byte, session *server.WSSession) {
 	defer func() {
 		if r := recover(); r != nil {
 			err := fmt.Errorf("panic in WebsocketService.Process(): %v", r)
-			logging.InfoMsg(ws.logger, "Panic in WebsocketService.Process()", structure.ErrorKey, err)
+			ws.logger.InfoMsg("Panic in WebsocketService.Process()", structure.ErrorKey, err)
 			if !session.Closed() {
 				ws.writeError(err.Error(), "", rpc.INTERNAL_ERROR, session)
 			}
diff --git a/txs/tx.go b/txs/tx.go
index 1133e948718f5bcc0188c1e6127fa12f90f2ce61..e79c1e457fdc625f83b42aad39974237e97111db 100644
--- a/txs/tx.go
+++ b/txs/tx.go
@@ -21,7 +21,7 @@ import (
 	"io"
 
 	acm "github.com/hyperledger/burrow/account"
-	ptypes "github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/permission/snatives"
 	"github.com/tendermint/go-wire"
 	"github.com/tendermint/go-wire/data"
 	"golang.org/x/crypto/ripemd160"
@@ -166,7 +166,7 @@ type (
 
 	PermissionsTx struct {
 		Input    *TxInput
-		PermArgs ptypes.PermArgs
+		PermArgs snatives.PermArgs
 		txHashMemoizer
 	}
 
diff --git a/txs/tx_test.go b/txs/tx_test.go
index 3a10bc394cd5b5f1ffb5382a8b8ccb53c9fe1b27..73c7da8e113baae7ef6f6ad8a45cbf85185dd5d9 100644
--- a/txs/tx_test.go
+++ b/txs/tx_test.go
@@ -22,6 +22,7 @@ import (
 
 	acm "github.com/hyperledger/burrow/account"
 	ptypes "github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/permission/snatives"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -189,7 +190,7 @@ func TestPermissionsTxSignable(t *testing.T) {
 			Amount:   12345,
 			Sequence: 250,
 		},
-		PermArgs: ptypes.SetBaseArgs(makeAddress("address1"), 1, true),
+		PermArgs: snatives.SetBaseArgs(makeAddress("address1"), 1, true),
 	}
 
 	signBytes := acm.SignBytes(chainID, permsTx)
@@ -220,7 +221,7 @@ func TestTxWrapper_MarshalJSON(t *testing.T) {
 func TestNewPermissionsTxWithSequence(t *testing.T) {
 	privateKey := acm.PrivateKeyFromSecret("Shhh...")
 
-	args := ptypes.SetBaseArgs(privateKey.PublicKey().Address(), ptypes.HasRole, true)
+	args := snatives.SetBaseArgs(privateKey.PublicKey().Address(), ptypes.HasRole, true)
 	permTx := NewPermissionsTxWithSequence(privateKey.PublicKey(), args, 1)
 	testTxMarshalJSON(t, permTx)
 }
diff --git a/txs/tx_utils.go b/txs/tx_utils.go
index a9056d51e07329161083ef433f3fa210e7f988c7..dd5ddae2455d1e718e05535d07b8376aa4081b56 100644
--- a/txs/tx_utils.go
+++ b/txs/tx_utils.go
@@ -18,7 +18,8 @@ import (
 	"fmt"
 
 	acm "github.com/hyperledger/burrow/account"
-	ptypes "github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/account/state"
+	"github.com/hyperledger/burrow/permission/snatives"
 )
 
 //----------------------------------------------------------------------------
@@ -31,7 +32,7 @@ func NewSendTx() *SendTx {
 	}
 }
 
-func (tx *SendTx) AddInput(st acm.Getter, pubkey acm.PublicKey, amt uint64) error {
+func (tx *SendTx) AddInput(st state.AccountGetter, pubkey acm.PublicKey, amt uint64) error {
 	addr := pubkey.Address()
 	acc, err := st.GetAccount(addr)
 	if err != nil {
@@ -74,7 +75,7 @@ func (tx *SendTx) SignInput(chainID string, i int, privAccount acm.PrivateAccoun
 //----------------------------------------------------------------------------
 // CallTx interface for creating tx
 
-func NewCallTx(st acm.Getter, from acm.PublicKey, to *acm.Address, data []byte,
+func NewCallTx(st state.AccountGetter, from acm.PublicKey, to *acm.Address, data []byte,
 	amt, gasLimit, fee uint64) (*CallTx, error) {
 
 	addr := from.Address()
@@ -116,7 +117,7 @@ func (tx *CallTx) Sign(chainID string, privAccount acm.PrivateAccount) {
 //----------------------------------------------------------------------------
 // NameTx interface for creating tx
 
-func NewNameTx(st acm.Getter, from acm.PublicKey, name, data string, amt, fee uint64) (*NameTx, error) {
+func NewNameTx(st state.AccountGetter, from acm.PublicKey, name, data string, amt, fee uint64) (*NameTx, error) {
 	addr := from.Address()
 	acc, err := st.GetAccount(addr)
 	if err != nil {
@@ -162,7 +163,7 @@ func NewBondTx(pubkey acm.PublicKey) (*BondTx, error) {
 	}, nil
 }
 
-func (tx *BondTx) AddInput(st acm.Getter, pubkey acm.PublicKey, amt uint64) error {
+func (tx *BondTx) AddInput(st state.AccountGetter, pubkey acm.PublicKey, amt uint64) error {
 	addr := pubkey.Address()
 	acc, err := st.GetAccount(addr)
 	if err != nil {
@@ -237,7 +238,7 @@ func (tx *RebondTx) Sign(chainID string, privAccount acm.PrivateAccount) {
 //----------------------------------------------------------------------------
 // PermissionsTx interface for creating tx
 
-func NewPermissionsTx(st acm.Getter, from acm.PublicKey, args ptypes.PermArgs) (*PermissionsTx, error) {
+func NewPermissionsTx(st state.AccountGetter, from acm.PublicKey, args snatives.PermArgs) (*PermissionsTx, error) {
 	addr := from.Address()
 	acc, err := st.GetAccount(addr)
 	if err != nil {
@@ -251,7 +252,7 @@ func NewPermissionsTx(st acm.Getter, from acm.PublicKey, args ptypes.PermArgs) (
 	return NewPermissionsTxWithSequence(from, args, sequence), nil
 }
 
-func NewPermissionsTxWithSequence(from acm.PublicKey, args ptypes.PermArgs, sequence uint64) *PermissionsTx {
+func NewPermissionsTxWithSequence(from acm.PublicKey, args snatives.PermArgs, sequence uint64) *PermissionsTx {
 	input := &TxInput{
 		Address:   from.Address(),
 		Amount:    1, // NOTE: amounts can't be 0 ...